#include #include #include #include #include #include #include "netdevice.h" #define PROC_NET_DEV "/proc/net/dev" #define NETDEVICE_MAX 100 static NETDEVICE netdevice[NETDEVICE_MAX]; static void netdevice_add_name( char *name ) { NETDEVICE ifn; NETDEVICE *ifp; //fprintf(stderr,"netdevice_add_name: %s\n", name); for (ifp=netdevice; (ifn=*ifp); ifp=&ifn->next) { if ( strcmp( ifn->name, name ) == 0 ) { return; } } if (!(*ifp=(NETDEVICE)malloc(sizeof(**ifp)))) return; ifn=*ifp; ifn->next=NULL; if (strlen(name)>sizeof(ifn->name)-1) name[sizeof(ifn->name)-1]='\0'; strncpy(ifn->name, name, NETDEVICE_LENGTH); ifn->ip = 0; ifn->netmask = 0; ifn->ip_alfa[0] = '\0'; ifn->flags = 0; ifn->deny_icmp_echo_request = 1; ifn->deny_icmp_time_exceeded = 1; if ( strncmp( ifn->name, "sl", 2 ) == 0 ) { ifn->status_if = STATUS_IF_DOWN; } else { ifn->status_if = STATUS_IF_INIT; } ifn->status_fw = STATUS_FW_INIT; return; } static char *get_netdevice_name(char *name, char *p) { while (isspace(*p)) p++; while (*p) { if (isspace(*p)) break; if (*p == ':') { /* could be an alias */ char *dot = p, *dotname = name; *name++ = *p++; while (isdigit(*p)) *name++ = *p++; if (*p != ':') { /* it wasn't, backup */ p = dot; name = dotname; } if (*p == '\0') return NULL; p++; break; } *name++ = *p++; } *name++ = '\0'; return p; } static char check_RFC1918( struct in_addr net ) { if ( ( strcmp( inet_ntoa( net ), "10.0.0.0" ) > 0 && strcmp( inet_ntoa( net ), "10.255.255.255" ) < 0 ) || ( strcmp( inet_ntoa( net ), "172.16.0.0" ) > 0 && strcmp( inet_ntoa( net ), "172.31.255.255" ) < 0 ) || ( strcmp( inet_ntoa( net ), "192.168.0.0" ) > 0 && strcmp( inet_ntoa( net ), "192.168.255.255" ) < 0 ) ) { //fprintf(stderr,"RFC1918: %s\n", inet_ntoa( net ) ); return( (char)1 ); } //fprintf(stderr,"No RFC1918: %s\n", inet_ntoa( net ) ); return( (char)0 ); } /* Fetch the netdevice configuration from the kernel. */ static void if_fetch( NETDEVICE ifn ) { static int fd = 0; struct ifreq ifr; if ( fd == 0 ) { fd = socket(AF_INET, SOCK_DGRAM, 0); if ( fd < 0) { syslog(LOG_ERR, "Socket error"); exit(1); } } strcpy(ifr.ifr_name, ifn->name); if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) return; ifn->flags = ifr.ifr_flags; strcpy(ifr.ifr_name, ifn->name); ifr.ifr_addr.sa_family = AF_INET; if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { uint32_t ip; struct sockaddr_in *sin; sin = (struct sockaddr_in *)&ifr.ifr_addr; strncpy( ifn->ip_alfa, inet_ntoa( sin->sin_addr ), IP_ALFA ); ip = ntohl( sin->sin_addr.s_addr ); if ( ip != ifn->ip ) { /* * Change of ip address for netdevice */ ifn->status_fw = STATUS_FW_DO; ifn->ip = ip; ifn->RFC1918 = check_RFC1918( sin->sin_addr ); } strcpy(ifr.ifr_name, ifn->name); if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0) { ifn->netmask = 0; } else { sin = (struct sockaddr_in *)&ifr.ifr_netmask; ifn->netmask = ntohl( sin->sin_addr.s_addr ); strncpy( ifn->netmask_alfa, inet_ntoa( sin->sin_addr ), IP_ALFA ); } //if ( ifn->status_fw == STATUS_FW_DO ) //fprintf(stderr,"if_fetch: new ip %s %s %s flags=%x\n", ifn->name, ifn->ip_alfa, ifn->netmask_alfa, ifn->flags ); if ( strncmp( ifn->name, "sl", 2 ) != 0 ) { ifn->status_if = STATUS_IF_UP; } return; } else { ifn->ip = 0; ifn->ip_alfa[0] = '\0'; if ( ifn->status_fw == STATUS_FW_DONE ) { /* * This netdevice does not work any more. * Firewall is to be turned off. */ ifn->status_fw = STATUS_FW_DO; } ifn->status_if = STATUS_IF_DOWN; //fprintf(stderr,"if_fetch: ioctl fail: %s\n", ifn->name ); } return; } NETDEVICE *netdevice_read( ) { char buf[300]; NETDEVICE ifn; FILE *f; f = fopen (PROC_NET_DEV, "r"); if ( f == NULL ) { return( NULL ); } /* * Skip the first line (title line) */ fgets(buf,sizeof(buf)-1,f); while (fgets(buf,sizeof(buf)-1,f)!=NULL){ char name[20]; get_netdevice_name( name, buf ); if ( strcmp( name, "face" ) == 0 ) continue; netdevice_add_name( name ); } fclose( f ); for (ifn=netdevice[0];ifn;ifn=ifn->next) { if_fetch( ifn ); if ( ! (ifn->flags & IFF_UP) ) { continue; } } return( netdevice ); }