Changing MAC address causes to stop telnet in VxWorks - vxworks

I need to change dynamically MAC address in VxWorks 7.
MAC address has been correctly changed.
After changing the MAC address, I can not use telnet and ping to the interface.
Using VxWorks 7, Arm, dcc.
// in usrAppInit()
struct ifreq ifr;
int s;
s = socket(AF_INET,SOCK_DGRAM,0);
memcpy(ifr.ifr_name,"eth0",5);
ifr.ifr_addr.sa_data[0] = 0x01;
ifr.ifr_addr.sa_data[1] = 0x02;
ifr.ifr_addr.sa_data[2] = 0x03;
ifr.ifr_addr.sa_data[3] = 0x04;
ifr.ifr_addr.sa_data[4] = 0x05;
ifr.ifr_addr.sa_data[5] = 0x06;
ifr.ifr_addr.sa_family = AF_INET;
ioctl(s, SIOCSIFLLADDR, &ifr); // eth0 mac address changed to 01:02:03:04:05:06
close(s);
After changing MAC address,
"ping" and "telnet" can not reach to that interface from PC.
"arp" command displays new MAC address.

Thanks to JaeMann Yeh, this worked for me:
ifconfig ("qfec0 lladdr 00:11:22:33:44:55")

You can use ifconfig to change the MAC address in your c file. For example,
ipcom_run_cmd("ifconfig qfec0 lladdr 00:11:22:33:44:55");
I have tested it and it worked fine.

You've set the least significant bit in byte 0. That indicates it's a multicast address, don't set your mac address to a multicast address.
Set it to something else , e.g.
ifr.ifr_addr.sa_data[0] = 0x00;

Related

IPv6 Compatibility Issues with Low-Level C API's [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Apple requires IPv6 Compatibility. Seems a little premature, but I suppose someone has to force it's wide adoption.
I have a client who has some legacy code that will no longer be approved for the App Store because of this incompatibility. I did not write the software by myself, and specifically have never touched this part of the code. I am not much of a ninja when it comes to low-level C networking.
I told the client that part of the problem was that they had an IPv4-only server and had us hardcode an IPv4 address to that server. I updated the IPv4 address to a domain name and told them their servers had to support IPv6. So, they moved them all over, and flipped the switch before any testing could be done. I was notified a few days ago that all their software on the store no longer worked. That's the predicament we are in.
Here is one of potentially many issues that I could use some help on.
Not only does the server that is connected to the port not respond to IPv6, but there are some lower level APIs that are being used that are incompatible.
The first thing I encountered is the use of gethostbyname(). Apparently this is not IPv6 capable. I have been trying to fix it with getaddrinfo() but my sockaddr's are not quite the same.
The second issue I can see is that apparently I need to be using AF_UNSPEC instead of AF_INET. So I am attempting to open a socket in the following way:
int sockfd = socket(AF_UNSPEC, SOCK_STREAM, 0);
I always get -1.
If I open a sock using AF_INET I get further, but then I have this issues:
otherAddr sockaddr * 0x618000220680 0x0000618000220680
sa_len __uint8_t '\x1c'
sa_family sa_family_t '\x1e'
sa_data char [14] "\x13\x88"
otherAddrCast sockaddr * 0x7000052d3c28 0x00007000052d3c28
sa_len __uint8_t '\0'
sa_family sa_family_t '\0'
sa_data char [14] "\x13\x88\"Ԛ\\"
So some of the sa_data is the same. and if I don't cast the sockaddr_in to a struct sockaddr* then the sa_data is the same.
Problem is I don't know what most of this means. Help?
EDIT: Here is my code. Assume that I am only getting 1 addr back (because I am)
struct hostent* server = gethostbyname([_hostname UTF8String]);
struct addrinfo *ai;
struct addrinfo hints;
memset(&hints, 0x00, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
NSString* portString = [NSString stringWithFormat:#"%d", _port];
getaddrinfo([_hostname UTF8String], [portString cStringUsingEncoding:kCFStringEncodingASCII] , &hints, &ai);
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
bcopy(server->h_addr, &addr.sin_addr.s_addr, server->h_length);
addr.sin_port = htons(_port);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
_addr = (struct sockaddr*)&addr;
int status = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
int status2 = connect(socket(ai->ai_family,ai->ai_socktype,0), ai->ai_addr, ai->ai_addrlen);
You are NOT supposed to use AF_UNSPEC with socket() at all. You MUST use either AF_INET (IPv4) or AF_INET6 (IPv6).
You can use AF_UNSPEC with the hints input parameter of getaddrinfo() to indicate that you are willing to accept both IPv4 and IPv6 addresses as output. The actual addresses in the output will be either AF_INET or AF_INET6. Or, you can set the hints to AF_INET for IPv4-only output. Or AF_INET6 for IPv6-only output.
You are supposed to loop through the list that is returned by getaddrinfo(). For each address in the list:
pass its ai_family, ai_socktype, and ai_protocol fields to socket()
then pass its ai_addr and ai_addrlen fields to bind() (servers) or connect() (clients).
Repeat this for all addresses reported for a listening server, and for all addresses reported for a client until one successfully connects.
This way, each socket you create matches the IP version of the address it is working with, and you are passing an appropriate matching sockaddr_in (IPv4) or sockaddr_in6 (IPv6) to bind()/connect().
Once you have successful listening server socket(s), or a successfully connected client socket, if you need to retrieve an IP from a socket using accept(), getsockname() or getpeername(), be sure to pass it a sockaddr_storage struct to fill in. sockaddr_storage is large enough to hold all defined sockaddr-based structures (and there are many). If successful, you can then type-cast it to a sockaddr_in or sockaddr_in6 based on its sa_family field (AF_INET or AF_INET6, respectively). Same goes for other similar functions, like inet_pton() and inet_ntop().
Update: given the client code you have shown, try this instead:
struct addrinfo hints = {0};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
NSString* portString = [NSString stringWithFormat:#"%d", _port];
struct addrinfo *ai;
int sockfd = -1;
int status = getaddrinfo([_hostname UTF8String], [portString cStringUsingEncoding:kCFStringEncodingASCII] , &hints, &ai);
if (status == 0) {
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd == -1) {
status = errno;
}
else if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
status = errno;
close(sockfd);
sockfd = -1;
}
freeaddrinfo(ai);
}
if (sockfd == -1) {
// handle status error as needed...
}
else {
// use sockfd as needed...
close(sockfd);
}

(UDP) GVCP BroadCast not functioning

Environment: Windows Socket Programming using VC++ 2010
GVCP : GigE Vision Control Protocol
GVCP = UDP+(GVCP Header Data+Payload Data). so basically on top its a UDP only
for Detecting GigE Sensor (Camera) need to first Broadcast a GVCP packet (containing Gvcp Payload data), using Broadcast address 255.255.255.255
but i am able to broadcast only by 192.168.1.255 (as seen on wire-shark) when i change broadcast address 255.255.255.255 nothing is visible on wire-shark nor on other machine
so problem is not able to broadcast using IP 255.255.255.255 using UDP/WinSock
able to start broadcasting the GVCP packet its just a socket creation error the correct one is below
//---------------------DATA SENDER------------------------------
struct sockaddr_in Sender_addr;
int Sender_addrlen = sizeof(Sender_addr);
Sender_addr.sin_family = AF_INET;
Sender_addr.sin_port = htons(CAMPORT); //BROADCAST_PORT);
Sender_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); //Broadcast
IP Here");
//---------------------DATA RECEIVER----------------------------
struct sockaddr_in Recv_addr;
int Recv_addrlen = sizeof(Recv_addr);
Recv_addr.sin_family = AF_INET;
Recv_addr.sin_port = htons(PCPORT);
Recv_addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sock,(sockaddr*)&Recv_addr,sizeof(Recv_addr))<0)
{
perror("bind");
_getch;
closesocket(sock);
}
//and then send command for GVCP packet (GVCP packet Structure is )
TxBuff[0] = 0x42;
TxBuff[1] = 0x01;
TxBuff[2] = 0x00;
TxBuff[3] = 0x02;
TxBuff[4] = 0x00;
TxBuff[5] = 0x00;
TxBuff[6] = 0x00;
TxBuff[7] = 0x02;
if(sendto(sock,TxBuff,TxBuffSize,0,(struct sockaddr
*)&Sender_addr,sizeof(Sender_addr)) <0)
{
perror("send: error ");
_getch();
closesocket(sock);
}

Build up multi vxworks in vmware

when I built up one vxworks in vmware it works. But when I create more two vxworks seperately with different IP, the second vxworks fails with(log is from vxware.log):
2015-09-02T09:10:45.057+08:00| vcpu-0| W110: VLANCE: RDP OUT to unknown Register 100
2015-09-02T09:10:45.057+08:00| vcpu-0| I120: VNET: MACVNetPort_SetPADR: Ethernet0: can't set PADR (0)
2015-09-02T09:10:45.057+08:00| vcpu-0| I120: Msg_Post: Warning
2015-09-02T09:10:45.057+08:00| vcpu-0| I120: [msg.vnet.padrConflict] MAC address 00:0C:29:5A:23:AF of adapter Ethernet0 is within the reserved address range or is in use by another virtual adapter on your system. Adapter Ethernet0 may not have network connectivity.
I am sure each vxworks OS got its own MAC address. Another point is that I created the second vxworks through copying the files from the first one.
Forgive me.
Remove the macro VXWORKS_RUN_ON_VMWARE and any related code in sysLn97xEnd.c.
Everything works perfectly under VMWorkstation 11.
MAC can be set under vm machine's config page.
Maybe those macro is for the far previous version of vmworkstation.
setting mac address in vmware does not work.
you need a function to generate different mac address while system booting.
each copy of the vm machines will need to build a differenet bootrom and a vxworks.
(simplely use -D MACRO in (.wpj)MAKEFILE to switch macs between different projects with a single header.)
here is a dirty solution for setting multi macs in one vm machine:
0.
define the mac addresses and a function to access it in ln97xEnd.c.
\#define LN97_MAX_IP (4)
int ln97EndLoaded = 0;
char ln97DefineAddr[LN97_MAX_IP][6] = {
{0x00, 0x0c, 0x29, 0x5a, 0x23, 0xa0},
{0x00, 0x0c, 0x29, 0x5a, 0x23, 0xa1},
{0x00, 0x0c, 0x29, 0x5a, 0x23, 0xa2},
{0x00, 0x0c, 0x29, 0x5a, 0x23, 0xa3}
};
END_OBJ * ln97xEndList[LN97_MAX_IP] = {NULL, NULL, NULL, NULL};
char * ln97xFindDefinedAddr(LN_97X_DRV_CTRL * pDrvCtrl)
{
int i;
for (i = 0; i endObj)
{
return ln97DefineAddr[i];
}
}
if (i
1.
Modify ln97xEndLoad() in ln97xEnd.c to init different mac (and store the END_OBJ* if needed).
END_OBJ * ln97xEndLoad
...
DRV_LOG (DRV_DEBUG_LOAD, "Done loading ln97x...\n", 1, 2, 3, 4, 5, 6);
/** add to save END_OBJ* */
if (ln97EndLoaded endObj;
ln97EndLoaded++;
}
/** end add */
return (&pDrvCtrl->endObj);
...
2.
change sysLan97xEnetAddrGet() in sysLn97xEnd.c.
aprom should not be set by ln97xFindDefinedAddr() instead of "00:0C:29:5A:23:AF".
char * ln97xFindDefinedAddr(LN_97X_DRV_CTRL * pDrvCtrl);
...
STATUS sysLan97xEnetAddrGet
...
{
char * addrDef = NULL;
...
/* modify by frankzhou to support in VMware */
\#define VXWORKS_RUN_ON_VMWARE
\#ifndef VXWORKS_RUN_ON_VMWARE
/* check for ASCII 'W's at APROM bytes 14 and 15 */
if ((aprom [0xe] != 'W') || (aprom [0xf] != 'W'))
{
logMsg ("sysLn97xEnetAddrGet: W's not stored in aprom\n",
0, 1, 2, 3, 4, 5);
return ERROR;
}
\#endif
\#ifdef VXWORKS_RUN_ON_VMWARE
/** add by bonex for multi mac addr */
addrDef = ln97xFindDefinedAddr(pDrvCtrl);
if (addrDef == NULL)
{
aprom[0]=0x00;
aprom\[1]=0x0c;
aprom[2]=0x29;
aprom[3]=0x5a;
aprom[4]=0x23;
aprom[5]=0xaf;
}
else
{
bcopy (addrDef, aprom, 6);
}
/** end by bonex */
\#endif
/* end by frankzhou */
...
3.
rebuild the bootrom, and rebuild the vxworks too.
result:
[telnet to vmware and check arpShow][1]
[1]: https://i.stack.imgur.com/kR9Uy.jpg
This is due to the setting of MAC address in sysLn97xEnd.c. This must be modified and rebuid the bootrom and vxworks image for another vxworks node, or it will render the conflict.

Setting i2c slave address for Devantech digital compass

I am trying to interface with a Devantech digital compass found here -
http://www.acroname.com/robotics/parts/R117-COMPASS.html
I am using a i2c-usb converter to plug it into my laptop -
http://www.robot-electronics.co.uk/htm/usb_i2c_tech.htm
First of all, I do not know much about electrical engineering. I have a good idea of the bare basics, but after that I get lost.
I am trying to follow this tutorial -
https://xgoat.com/wp/2007/11/11/using-i2c-from-userspace-in-linux/
However I get stuck at the very beginning when I try to set the device address.
if( ioctl( fd, I2C_SLAVE, ADDRESS ) < 0 )
{
fprintf( stderr, "Failed to set slave address: %m\n" );
return 2;
}
returns "Failed to set slave address: Invalid argument"
I originally thought the address should be 0xC0 because a sentence in the manual for the compass reads "First send a start bit, the module address (0xC0)..." but that did not work.
Now I have a loop that just goes from 1 to 100 and tries each one for the address, but they all fail. The loop is -
for(int i=0x0;i<0x100;i++) {
if( ioctl( fd, I2C_SLAVE, i ) < 0 )
fprintf( stderr, "Failed to set slave address for address %i: %m\n", i );
}
I'm not sure what else to try. Right now, I just want to set the address so I can start attempting to read and write. Since the converter is what is actually connected to the pc, should I be using the address for that? And if so, where can I find it on that link with the information for it? If someone has an idea of what I could try or what is wrong that would be great.
EDIT:
Okay I have the code like this now -
#define ADDRESS 0x55
int fd = open("/dev/i2c-0", O_RDWR);
if (fd < 0) {
printf("\n<0, %m", errno);
return -1;
}
if( ioctl( fd, I2C_SLAVE, ADDRESS ) < 0 ) {
fprintf( stderr, "Failed to set slave address: %m\n" );
return 2;
}
if( i2c_smbus_write_byte( fd, 0xAA ) < 0 )
fprintf( stderr, "Failed to write 0xAA to I2C device: %m\n" );
It will set the address, but it won't write anything. Whenever I try to write to it, I get -
Failed to write 0xAA to I2C device: No such device or address
Why are your trying to send 0xAA to the device ?
To my understanding this is not a register for it (for the CMPS03, the only command is register 15 and its usage is not common: change the I2C address, factory reset, ...).
And 0x55 seems definitively not the address of the device ... 0xC0 should be the write one.
Could be that /dev/i2c-0 has not been created properly / is not correct?
How did you get /dev/ic2-0 created ?

Linux splice() returning EINVAL ("Invalid argument")

I'm trying to experiment with using splice (man 2 splice) to copy data from a UDP socket directly to a file. Unfortunately the first call to splice() returns EINVAL.
The man page states:
EINVAL Target file system doesn't support splicing; target file is opened in
append mode; neither of the descriptors refers to a pipe; or offset
given for nonseekable device.
However, I believe none of those conditions apply. I'm using Fedora 15 (kernel 2.6.40-4) so I believe splice() is supported on all filesystems. The target file should be irrelevant in the first call to splice, but for completeness I'm opening it via open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR). Both calls use a pipe and neither call uses an offset besides NULL.
Here's my sample code:
int sz = splice(sock_fd, 0, mPipeFds[1], 0, 8192, SPLICE_F_MORE);
if (-1 == sz)
{
int err = errno;
LOG4CXX_ERROR(spLogger, "splice from: " << strerror(err));
return 0;
}
sz = splice(mPipeFds[0], 0, file_fd, 0, sz, SPLICE_F_MORE);
if (-1 == sz)
{
int err = errno;
LOG4CXX_ERROR(spLogger, "splice to: " << strerror(err));
}
return 0;
sock_fd is initialized by the following psuedocode:
int sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK);
bind(sock_fd, ...);
Possibly related is that this code snippet is running inside a libevent loop. libevent is using epoll() to determine if the UDP socket is hot.
Found my answer. tl;dr - UDP isn't supported on the inbound side.
After enough Googling I stumbled upon a forum discussion and some test code which prints out a table of in/out fd types and their support:
$ ./a.out
in\out pipe reg chr unix tcp udp
pipe yes yes yes yes yes yes
reg yes no no no no no
chr yes no no no no no
unix no no no no no no
tcp yes no no no no no
udp no no no no no no
Yeah, it is definitely not supported for reading from a UDP socket, even in the latest kernels. References to the kernel source follow.
splice invokes do_splice in the kernel, which calls do_splice_to, which calls the splice_read member in the file_operations structure for the file.
For sockets, that structure is defined as socket_file_ops in net/socket.c, which initializes the splice_read field to sock_splice_read.
That function, in turn, contains this line of code:
if (unlikely(!sock->ops->splice_read))
return -EINVAL;
The ops field of the socket is a struct proto_ops. For an IPv4 UDP socket, it is initialized to inet_dgram_ops in net/ipv4/af_inet.c. Finally, that structure does not explicitly initialize the splice_read field of struct proto_ops; i.e., it initializes it to zero.
So sock_splice_read returns -EINVAL, and that propagates up.