/* net.c: Network interface manipulation * * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>, * The Silver Hammer Group, Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/time.h> #include <dirent.h> #include <errno.h> #include <termios.h> #include <string.h> #include <sys/ioctl.h> #include <fcntl.h> #ifdef __UC_LIBC__ #include <linux/sockios.h> #include <linux/socket.h> #include <linux/in.h> #include <linux/icmp.h> #include <linux/route.h> #include <linux/if.h> #else #include <sys/socket.h> #include <net/route.h> #include <net/if.h> #endif #include <netinet/in.h> #include <arpa/inet.h> #include <termios.h> #include <signal.h> #include <sys/time.h> #include "net.h" #define HAVE_NEW_ADDRT 1 #if HAVE_NEW_ADDRT #define mask_in_addr(x) (((struct sockaddr_in *)&((x).rt_genmask))->sin_addr.s_addr) #define full_mask(x) (x) #else #define mask_in_addr(x) ((x).rt_genmask) #define full_mask(x) (((struct sockaddr_in *)&(x))->sin_addr.s_addr) #endif extern int skfd; #ifdef L_openraw int skfd=-1; int open_raw_socket(void) { if (skfd != -1) close(skfd); skfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (skfd==-1) return -1; return 0; } #endif #ifdef L_closeraw int close_raw_socket(void) { if (skfd != -1) close(skfd); skfd = -1; return 0; } #endif #ifdef L_setifflags int setifflags(char *ifname, short flags) { struct ifreq ifr; int i; #ifdef DEBUG printf("Adding flags %x to %s\n", flags, ifname); #endif strcpy(ifr.ifr_name, ifname); if ((i=ioctl(skfd, SIOCGIFFLAGS, &ifr)) < 0) { fprintf(stdout, "SIOCGIFFLAGS = %d: %s (%d)\n", i, strerror(errno), errno); return(-1); } ifr.ifr_flags |= flags; if ((i=ioctl(skfd, SIOCSIFFLAGS, &ifr)) < 0) { fprintf(stdout, "SIOCSIFFLAGS = %d: %s (%d)\n", i, strerror(errno), errno); return(-1); } return(0); } #endif #ifdef L_resetifflags int resetifflags(char *ifname, short flags) { struct ifreq ifr; int i; #ifdef DEBUG printf("Adding flags %x to %s\n", flags, ifname); #endif strcpy(ifr.ifr_name, ifname); if ((i=ioctl(skfd, SIOCGIFFLAGS, &ifr)) < 0) { fprintf(stdout, "SIOCGIFFLAGS = %d: %s (%d)\n", i, strerror(errno), errno); return(-1); } ifr.ifr_flags &= ~flags; if ((i=ioctl(skfd, SIOCSIFFLAGS, &ifr)) < 0) { fprintf(stdout, "SIOCSIFFLAGS = %d: %s (%d)\n", i, strerror(errno), errno); return(-1); } return(0); } #endif #ifdef L_setifaddr int setifaddr(char * device, char * addr) { int i; struct ifreq ifr; struct sockaddr_in*in; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, device); in = (struct sockaddr_in*)&ifr.ifr_addr; in->sin_family = AF_INET; in->sin_port = 0; in->sin_addr.s_addr = inet_addr(addr); #ifdef DEBUG printf("IFADDR %s -> %s\n", device, addr); #endif if ((i=ioctl(skfd, SIOCSIFADDR, &ifr)) < 0) fprintf(stdout, "SIOCSIFADDR=%d: %d\n", i, errno); errno = 0; return 0; } #endif #ifdef L_setifdstaddr int setifdstaddr(char * device, char * addr) { int i; struct ifreq ifr; struct sockaddr_in*in; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, device); in = (struct sockaddr_in*)&ifr.ifr_addr; in->sin_family = AF_INET; in->sin_port = 0; in->sin_addr.s_addr = inet_addr(addr); #ifdef DEBUG printf("IFDSTADDR %s -> %s\n", device, addr); #endif if ((i=ioctl(skfd, SIOCSIFDSTADDR, &ifr)) < 0) fprintf(stdout, "SIOCSIFDSTADDR=%d: %d\n", i, errno); errno = 0; return 0; } #endif #ifdef L_setifbrdaddr int setifbrdaddr(char * device, char * addr) { int i; struct ifreq ifr; struct sockaddr_in*in; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, device); in = (struct sockaddr_in*)&ifr.ifr_addr; in->sin_family = AF_INET; in->sin_port = 0; in->sin_addr.s_addr = inet_addr(addr); #ifdef DEBUG printf("IFBRDADDR %s -> %s\n", device, addr); #endif if ((i=ioctl(skfd, SIOCSIFBRDADDR, &ifr)) < 0) fprintf(stdout, "SIOCSIFBRDADDR=%d: %d\n", i, errno); errno = 0; return 0; } #endif #ifdef L_setifnetmask int setifnetmask(char * device, char * mask) { int i; struct ifreq ifr; struct sockaddr_in*in; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, device); in = (struct sockaddr_in*)&ifr.ifr_addr; in->sin_family = AF_INET; in->sin_port = 0; in->sin_addr.s_addr = inet_addr(mask); #ifdef DEBUG printf("IFNETMASK %s -> %s\n", device, mask); #endif if ((i=ioctl(skfd, SIOCSIFNETMASK, &ifr)) < 0) fprintf(stdout, "SIOCSIFNETMASK=%d: %d\n", i, errno); errno = 0; return 0; } #endif #ifdef L_setifmtu int setifmtu(char * device, int mtu) { int i; struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, device); ifr.ifr_mtu = mtu; #ifdef DEBUG printf("SIFSMTU %s -> %d\n", device, mtu); #endif if ((i=ioctl(skfd, SIOCSIFMTU, &ifr)) < 0) fprintf(stdout, "SIOCSIFMTU=%d: %d\n", i, errno); errno = 0; return 0; } #endif #ifdef L_addroute void addroute(char * device, int flags, char * addr, char * netmask, char * gateway) { struct ifreq ifr; struct sockaddr_in*in; struct rtentry rt; unsigned long mask=0; int i; in = (struct sockaddr_in*)&ifr.ifr_addr; in->sin_family = AF_INET; in->sin_port = 0; in->sin_addr.s_addr = addr ? inet_addr(addr) : 0; if (gateway) flags |= RTF_GATEWAY; /* Clean out the RTREQ structure. */ memset((char *) &rt, 0, sizeof(struct rtentry)); rt.rt_flags = flags; rt.rt_dev = device; (*(struct sockaddr_in*)&rt.rt_dst) = *in; /*mask_in_addr(rt) = netmask ? inet_addr(netmask) : 0;*/ if (netmask) { in->sin_addr.s_addr = mask = inet_addr(netmask); (*(struct sockaddr_in*)&rt.rt_genmask) = *in; } in = (struct sockaddr_in*)&ifr.ifr_addr; in->sin_family = AF_INET; in->sin_port = 0; in->sin_addr.s_addr = gateway ? inet_addr(gateway) : 0; (*(struct sockaddr_in*)&rt.rt_gateway) = *in; #ifdef DEBUG printf("SIOCADDRT %s -> flags: %d, addr: %s, netmask: %s, gateway: %s\n", device, flags, addr, netmask, gateway); #endif if (netmask) { if (flags & RTF_HOST) printf("Warning: RTF_HOST and netmask don't go together\n"); if ((~mask) & ((~mask)+1)) printf("Warning: Bogus netmask\n"); in->sin_addr.s_addr = addr ? inet_addr(addr) : 0; if (in->sin_addr.s_addr & ~mask) printf("Warning: netmask doesn't match route address\n"); } if ((i=ioctl(skfd, SIOCADDRT, &rt)) < 0) fprintf(stdout, "SIOCADDRT=%d: %d\n", i, errno); } #endif #ifdef L_maskaddress char * maskaddress(const char * address, const char * mask) { unsigned long a, m; struct in_addr i; a = inet_addr(address); m = inet_addr(mask); i.s_addr = a & m; return inet_ntoa(i); } #endif #ifdef L_setifhwaddr int setifhwaddr(const char * device, const char * addr) { int i; unsigned char hw[6]; struct ifreq ifr; struct sockaddr_in*in; memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, device); for(i=0;addr && (i<6);i++) { char * next; hw[i] = strtol(addr, &next, 16) & 0xff; if (next) addr = next + 1; else addr = 0; } /* parse error */ if (i!=6) return -1; #ifdef DEBUG printf("IFHWADDR %s -> %s (", device, addr); for(i=0;i<6;i++) { printf("%02.2x", hw[i]); if (i<5) printf(":"); } printf(")\n"); #endif ifr.ifr_hwaddr.sa_family = AF_INET; memcpy(ifr.ifr_hwaddr.sa_data, &hw, 6); if ((i=ioctl(skfd, SIOCSIFHWADDR, &ifr)) < 0) fprintf(stdout, "SIOCSIFHWADDR=%d: %d\n", i, errno); errno = 0; return 0; } #endif