I thought if you can create two sockets.
Since you are using UDP, you can call bind + recvFrom on Raw Sock Fd and then manually unzip the IP header to determine TOS or TTL.
When you want to send, use DOCAM SockFd, so you don’t have to worry about actually creating the UDP and IP packet.
It is possible that problems such as the kernel can transfer the received buffer to both sockets or to a UDP socket instead of a Raw socket or only to a Raw socket. If so (or if it depends on the implementation), we will return to the square. However, you can try calling bind on the Raw socket and see if it helps. I know this can be a hack, but a network search for setsockopt for BSD returns nothing.
EDIT : I wrote an example program. It's kind of achieving a goal.
In the code below, two sockets are created (one raw and one udp). The udp socket is bound to the actual port that I expect to receive data, while the raw socket is bound to port 0. I tested this on Linux and, as I expected, any data for port 2905 is accepted by both sockets. However, I can get the TTL and TOS values. Do not reduce the quality of the code. I'm just experimenting if this will work.
Further EDIT: Disabled receiving through UDP socket. I further improved the code to disable UDP packet reception. Using setsockopt, I set the UDP socket receive buffer to 0 .. This ensures that the kernel does not forward the packet to the UDP socket. IMHO, now you can use the UDP socket exclusively for sending and the raw socket for reading. This should work for you in BSD and Solaris.
#include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<netinet/ip.h> #include<arpa/inet.h> #include<string.h> #include "protHeaders.x" #include "gen.h" int main(void) { S32 rawSockFd; S32 udpSockFd; struct sockaddr_in rsin; struct sockaddr_in usin; S32 one = 1; const S32* val = &one; struct timeval tv; fd_set rfds; S32 maxFd; S16 ret; S8 rawBuffer[2048]; S8 udpBuffer[2048]; struct sockaddr udpFrom,rawFrom; socklen_t rLen,uLen; memset(rawBuffer,0,sizeof(rawBuffer)); memset(udpBuffer,0,sizeof(udpBuffer)); memset(udpFrom,0,sizeof(udpFrom)); memset(rawFrom,0,sizeof(rawFrom)); if ((rawSockFd = socket(PF_INET,SOCK_RAW,IPPROTO_UDP)) < 0) { perror("socket:create"); RETVALUE(RFAILED); } /* doing the IP_HDRINCL call */ if (setsockopt(rawSockFd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one)) < 0) { perror("Server:setsockopt"); RETVALUE(RFAILED); } rsin.sin_family = AF_INET; rsin.sin_addr.s_addr = htonl(INADDR_ANY); rsin.sin_port = htons(0); usin.sin_family = AF_INET; usin.sin_addr.s_addr = htons(INADDR_ANY); usin.sin_port = htons(2905); if(bind(rawSockFd,(struct sockaddr *)&rsin, sizeof(rsin)) < 0 ) { perror("Server: bind failed"); RETVALUE(RFAILED); } if ((udpSockFd = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) { perror("socket:create"); RETVALUE(RFAILED); } if(bind(udpSockFd,(struct sockaddr *)&usin, sizeof(usin)) < 0 ) { perror("Server: bind failed on udpsocket"); RETVALUE(RFAILED); } /*set upd socket receive buffer to 0 */ one = 0; if (setsockopt(udpSockFd,SOL_SOCKET,SO_RCVBUF,(char *)&one,sizeof(one)) < 0) { perror("Server:setsockopt on udpsocket failed"); RETVALUE(RFAILED); } tv.tv_sec = 0; tv.tv_usec = 0; maxFd = (rawSockFd > udpSockFd)? rawSockFd:udpSockFd; while(1) { FD_ZERO(&rfds); FD_SET(rawSockFd,&rfds); FD_SET(udpSockFd,&rfds); ret = select(maxFd+1,&rfds,0,0,&tv); if ( ret == -1) { perror("Select Failed"); RETVALUE(RFAILED); } if(FD_ISSET(rawSockFd,&rfds)) { printf("Raw Socked Received Message\n"); if(recvfrom(rawSockFd,rawBuffer,sizeof(rawBuffer),0,&rawFrom,&rLen) == -1) { perror("Raw socket recvfrom failed"); RETVALUE(RFAILED); } /*print the tos */ printf("TOS:%x\n",*(rawBuffer+1)); printf("TTL:%x\n",*(rawBuffer+8)); } if(FD_ISSET(udpSockFd,&rfds)) { printf("UDP Socked Received Message\n"); if(recvfrom(udpSockFd,udpBuffer,sizeof(udpBuffer),0,&udpFrom,&uLen) == -1) { perror("Udp socket recvfrom failed"); RETVALUE(RFAILED); } printf("%s\n",udpBuffer); } } RETVALUE(ROK); }