001: /* 002: NAME 003: ifc-modoki - configure a network interface 004: 005: SYNOPSIS 006: ifc-modoki [interface] 007: ifc-modoki interface [address[/mask]|up|down] 008: */ 009: 010: #include 011: #include 012: #include 013: #include 014: #include 015: 016: #include 017: #include 018: #include 019: #include 020: #include 021: #include 022: 023: 024: #define SUCCESS (0) 025: #define FAILURE (1) 026: #define UP_INTF (10) 027: #define DOWN_INTF (11) 028: 029: struct interface { 030: struct interface* next; 031: 032: char name[IFNAMSIZ]; /* interface name */ 033: short type; /* if type */ 034: short flags; /* various flags */ 035: char hwaddr[32]; 036: 037: int has_ip; 038: struct sockaddr addr; /* IP address */ 039: struct sockaddr broadaddr; /* IP broadcast address */ 040: struct sockaddr netmask; /* IP network mask */ 041: }; 042: 043: static struct interface* intf=NULL; 044: static int skfd=-1; 045: 046: 047: 048: static int fetchInterface( struct interface* ptr ) 049: { 050: struct ifreq ifr; 051: 052: strcpy(ifr.ifr_name, ptr->name); 053: if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) { 054: perror("ioctl"); 055: exit(1); 056: } 057: ptr->flags = ifr.ifr_flags; 058: 059: strcpy(ifr.ifr_name, ptr->name); 060: if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) 061: memset(ptr->hwaddr, 0, 32); 062: else 063: memcpy(ptr->hwaddr, ifr.ifr_hwaddr.sa_data, 8); 064: ptr->type = ifr.ifr_hwaddr.sa_family; 065: 066: strcpy(ifr.ifr_name, ptr->name); 067: ifr.ifr_addr.sa_family = AF_INET; 068: 069: if(ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { 070: ptr->has_ip = 1; 071: ptr->addr = ifr.ifr_addr; 072: 073: strcpy(ifr.ifr_name, ptr->name); 074: if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) 075: memset(&ptr->broadaddr, 0, sizeof(struct sockaddr)); 076: else 077: ptr->broadaddr = ifr.ifr_broadaddr; 078: 079: strcpy(ifr.ifr_name, ptr->name); 080: if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) 081: memset(&ptr->netmask, 0, sizeof(struct sockaddr)); 082: else 083: ptr->netmask = ifr.ifr_netmask; 084: } else 085: memset(&ptr->addr, 0, sizeof(struct sockaddr)); 086: 087: return SUCCESS; 088: } 089: 090: 091: static int lookupAllInterface(void) 092: { 093: FILE* fp; 094: char buf[256]; 095: intf=NULL; 096: 097: fp = fopen( "/proc/net/dev", "r" ); 098: 099: if(fp) { 100: fgets(buf, sizeof(buf), fp); 101: fgets(buf, sizeof(buf), fp); 102: while( fgets(buf, sizeof(buf), fp) !=NULL ) { 103: char *name = strtok( buf, " :" ); /* I don't recommand strtok() */ 104: 105: if( name ) { 106: struct interface* new_intf; 107: new_intf = (struct interface*)malloc( sizeof(struct interface) ); 108: if( !new_intf ) { 109: perror("malloc"); 110: exit(1); 111: } 112: strcpy( new_intf->name, name); 113: fetchInterface( new_intf ); 114: 115: if( intf ) { 116: new_intf->next=intf; 117: intf = new_intf; 118: } else { 119: intf = new_intf; 120: } 121: } 122: } 123: fclose(fp); 124: } else { 125: printf("could't open /proc/net/dev\n"); 126: exit(1); 127: } 128: return SUCCESS; 129: } 130: 131: 132: static int getIPMask(char* str, struct in_addr* ipaddr, int* mask) 133: { 134: int ret=SUCCESS; 135: char* p; 136: 137: if( strncasecmp( str, "up" ,1) == 0 ) return UP_INTF; 138: if( strncasecmp( str, "down",1 ) == 0 ) return DOWN_INTF; 139: 140: p = strstr( str, "/"); 141: if( p ) { 142: *p = (char)NULL; 143: } 144: 145: if(!inet_aton(str, ipaddr) ) { 146: printf("Invalid IP Address : %s!\n", str); 147: exit(1); 148: } 149: 150: if( !p ) { 151: struct in_addr tmp = *ipaddr; 152: 153: tmp.s_addr = ntohl(tmp.s_addr); 154: if (((tmp.s_addr & 0xFF000000) >> 24) <= 127) 155: *mask = 8; /* class A */ 156: else if (((tmp.s_addr & 0xFF000000) >> 24) <= 191) 157: *mask = 16; /* class B */ 158: else 159: *mask = 24; /* class C */ 160: } else { 161: *mask = atoi(p+1); 162: } 163: 164: if( *mask < 1 || *mask > 31 ) { 165: printf("Invalid mask : %d bits!\n", *mask); 166: exit(1); 167: } 168: 169: return ret; 170: } 171: 172: static void printInterfaceStatus( struct interface* ptr ) 173: { 174: if( ! (ptr->flags & IFF_UP) ) return; 175: 176: printf("%-10.10s ", ptr->name); 177: if( ptr->has_ip ) { 178: char str_addr[20]; 179: char str_broadaddr[20]; 180: char str_netmask[20]; 181: 182: strncpy(str_addr, 183: inet_ntoa( ((struct sockaddr_in*)&ptr->addr)->sin_addr ), 20 ); 184: strncpy(str_broadaddr, 185: inet_ntoa( ((struct sockaddr_in*)&ptr->broadaddr)->sin_addr ),20 ); 186: strncpy(str_netmask, 187: inet_ntoa( ((struct sockaddr_in*)&ptr->netmask)->sin_addr ), 20 ); 188: 189: printf("inet addr:%-15.15s Bcast:%-15.15s Mask:%-15.15s", 190: str_addr, str_broadaddr, str_netmask ); 191: } 192: printf("\n%-10.10s ", ""); 193: if (ptr->flags == 0) printf("[NO FLAGS] "); 194: if (ptr->flags & IFF_UP) printf("UP "); 195: if (ptr->flags & IFF_BROADCAST) printf("BROADCAST "); 196: if (ptr->flags & IFF_DEBUG) printf("DEBUG "); 197: if (ptr->flags & IFF_LOOPBACK) printf("LOOPBACK "); 198: if (ptr->flags & IFF_RUNNING) printf("RUNNING "); 199: if (ptr->flags & IFF_MULTICAST) printf("MULTICAST "); 200: printf("\n"); 201: printf("\n"); 202: } 203: 204: 205: static void printInterface(char* dev) 206: { 207: struct interface* ptr=intf; 208: 209: if( dev ) { 210: while( ptr ) { 211: if( strcmp(ptr->name,dev)==0 ) break; 212: ptr = ptr->next; 213: } 214: if( ptr ) { 215: printInterfaceStatus(ptr); 216: } else { 217: printf("could not find %s\n", dev); 218: exit(1); 219: } 220: } else { 221: while( ptr ) { 222: printInterfaceStatus( ptr); 223: ptr = ptr->next; 224: } 225: } 226: } 227: 228: 229: static void configInterface(char* dev, struct in_addr ipaddr, int mask ) 230: { 231: struct ifreq req; 232: struct in_addr netmask; 233: struct in_addr broadaddr; 234: struct sockaddr_in addr; 235: 236: 237: netmask.s_addr = htonl( 0xffffffff << (32-mask) ); 238: broadaddr.s_addr = htonl(ntohl(ipaddr.s_addr) | ~ntohl(netmask.s_addr)); 239: 240: strcpy(req.ifr_name, dev); 241: addr.sin_family = AF_INET; 242: addr.sin_port = 0; 243: 244: 245: memcpy(&addr.sin_addr, &ipaddr, sizeof(struct in_addr)); 246: memcpy(&req.ifr_addr, &addr, sizeof(addr)); 247: if (ioctl(skfd, SIOCSIFADDR, &req)) { 248: perror("SIOCSIFADDR Error!"); 249: close(skfd); 250: exit(1); 251: } 252: 253: memcpy(&addr.sin_addr, &broadaddr, sizeof(struct in_addr)); 254: memcpy(&req.ifr_broadaddr, &addr, sizeof(addr)); 255: if (ioctl(skfd, SIOCSIFBRDADDR, &req)) { 256: perror("SIOCSIFBRDADDR Error!"); 257: close(skfd); 258: exit(1); 259: } 260: 261: memcpy(&addr.sin_addr, &netmask, sizeof(struct in_addr)); 262: memcpy(&req.ifr_netmask, &addr, sizeof(addr)); 263: if (ioctl(skfd, SIOCSIFNETMASK, &req)) { 264: perror("SIOCSIFNETMASK Error!"); 265: close(skfd); 266: exit(1); 267: } 268: 269: req.ifr_flags = IFF_UP | IFF_RUNNING | IFF_BROADCAST; 270: if (ioctl(skfd, SIOCSIFFLAGS, &req)) { 271: perror("SIOCSIFFLAGS Error!"); 272: close(skfd); 273: exit(1); 274: } 275: } 276: 277: 278: static void bringInterface(char* dev, int c) 279: { 280: struct ifreq ifr; 281: 282: strcpy(ifr.ifr_name, dev); 283: if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) { 284: fprintf(stderr, "%s: unknown interface: %s\n", 285: dev, strerror(errno)); 286: exit(1); 287: } 288: 289: strcpy(ifr.ifr_name, dev); 290: if( c == UP_INTF ) { 291: ifr.ifr_flags |= IFF_UP; 292: } else if( c == DOWN_INTF ) { 293: ifr.ifr_flags &= ~IFF_UP; 294: } 295: 296: if (ioctl(skfd, SIOCSIFFLAGS, &ifr) < 0) { 297: perror("SIOCSIFFLAGS"); 298: exit(1); 299: } 300: } 301: 302: 303: static void Usage(void) 304: { 305: printf("Usage: ifc-modoki [interface]\n"); 306: printf(" ifc-modoki interface IPaddress|up|down\n"); 307: exit(1); 308: } 309: 310: 311: int main(int argc,char* argv[]) 312: { 313: skfd = socket(AF_INET, SOCK_DGRAM, 0); 314: if(skfd < 0) { 315: close(skfd); 316: perror("socket"); 317: return(1); 318: } 319: 320: lookupAllInterface(); 321: 322: if( argc == 1 ) { 323: printInterface(NULL); 324: } else if(argc == 2 ) { 325: printInterface(argv[1]); 326: } else if(argc == 3 ) { 327: struct in_addr ipaddr; 328: int mask; 329: int rc; 330: 331: rc = getIPMask(argv[2], &ipaddr, &mask); 332: switch(rc) { 333: case 0: 334: configInterface(argv[1], ipaddr, mask ); 335: break; 336: case UP_INTF: 337: case DOWN_INTF: 338: bringInterface(argv[1], rc); 339: break; 340: default: 341: close(skfd); 342: Usage(); 343: } 344: } else { 345: Usage(); 346: } 347: 348: close(skfd); 349: return 0; 350: } 351: 352: 353: /* 354: * Local variables: 355: * complie-command: "gcc -Wall -o ifc-modoki ifc-modoki.c" 356: * End: 357: */