1/****************************************************************************** 2 * Fichier Module :util.c - An IGMPv3-router implementation 3 ****************************************************************************** 4 * Fichier : util.c 5 * Description: Implementation des divers routines 6 * Mars 2001 7 * Date : May 18, 2000 8 * Auteur : lahmadi@loria.fr 9 * Last Modif : Aout 2, 2001 10 * 11 *****************************************************************************/ 12#include <stdarg.h> 13/*#include <sys/types.h> 14#include <sys/socket.h> 15#include <sys/ioctl.h> 16#include <net/if.h> 17#include <net/route.h>*/ 18 19#include "igmprt.h" 20 21int log_level; 22 23/* 24 * Set/reset the IP_MULTICAST_LOOP. Set/reset is specified by "flag". 25 */ 26void k_set_loop(int socket, int flag) 27{ 28 u_char loop; 29 30 loop = flag; 31 if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP, 32 (char *)&loop, sizeof(loop)) < 0) 33 printf("setsockopt IP_MULTICAST_LOOP %u\n", loop); 34} 35 36/* 37 * Set the IP_MULTICAST_IF option on local interface ifa. 38 */ 39void k_set_if(int socket, u_long ifa) 40{ 41 struct in_addr adr; 42 43 adr.s_addr = ifa; 44 if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, 45 (char *)&adr, sizeof(adr)) < 0) 46 printf("setsockopt IP_MULTICAST_IF %s\n", strerror(errno)); 47} 48 49 50/* 51 * void debug(int level) 52 * 53 * Write to stdout 54 */ 55void debug(int level, const char* fmt, ...) 56{ 57 va_list args; 58 59 if (level < log_level) 60 return; 61 va_start(args, fmt); 62 vprintf(fmt, args); 63 va_end(args); 64} 65 66/* 67 * u_short in_cksum(u_short *addr, int len) 68 * 69 * Compute the inet checksum 70 */ 71unsigned short in_cksum(unsigned short *addr, int len) 72{ 73 int nleft = len; 74 int sum = 0; 75 unsigned short *w = addr; 76 unsigned short answer = 0; 77 78 while (nleft > 1) { 79 sum += *w++; 80 nleft -= 2; 81 } 82 if (nleft == 1) { 83 *(unsigned char*)(&answer) = *(unsigned char*)w; 84 sum += answer; 85 } 86 sum = (sum >> 16) + (sum & 0xffff); 87 answer = ~sum; 88 return (answer); 89} 90 91char* get_if_by_idx(int idx, char* name) 92{ 93 FILE *fp; 94 int row = 0, strLen = 0, i; 95 char str[10] = {0}; 96 char buf[512] = {0}; 97 98 if (!(fp = fopen("/proc/net/dev", "r"))) { 99 return NULL; 100 } 101 102 for (row = 0; row < (idx + 2); row++) { 103 if(!fgets(buf, sizeof(buf), fp)) 104 return NULL; 105 } 106 107 i = 0; 108 strLen = 0; 109 while ((buf[i] != '\0') && (buf[i] != '\n') && strLen<IFNAMSIZ) { 110 if ((buf[i] != ' ') && (buf[i] != ':') && 111 (buf[i] != '\0') && (buf[i] != '\n')) { 112 str[strLen] = buf[i]; 113 strLen++; 114 } 115 else if (buf[i] == ':') { 116 str[strLen] = '\0'; 117 buf[i] = ' '; 118 break; 119 } 120 buf[i] = ' '; 121 i++; 122 } 123 strcpy(name, str); 124 125 fclose(fp); 126 return (name); 127} 128 129/* 130 * interface_list_t* get_interface_list(short af, short flags, short unflags) 131 * 132 * Get the list of interfaces with an address from family af, and whose flags 133 * match 'flags' and don't match 'unflags'. 134 */ 135interface_list_t* get_interface_list(short af, short flags, short unflags) 136{ 137 char *p, buf[IFNAMSIZ]; 138 interface_list_t *ifp, *ifprev, *list; 139 struct sockaddr *psa; 140 struct ifreq ifr; 141 int sockfd; 142 int i, err; 143 144 sockfd = socket(PF_INET, SOCK_DGRAM, 0); 145 if (sockfd <= 0) 146 return NULL; 147 148 list = ifp = ifprev = NULL; 149 for (i=1; ; i++) { 150 //p = if_indextoname(i, buf); 151 p = get_if_by_idx(i, buf); 152 if (p == NULL) 153 break; 154 155 strncpy(ifr.ifr_name, p, IFNAMSIZ); 156 err = ioctl(sockfd, SIOCGIFADDR, (void*)&ifr); 157 psa = &ifr.ifr_ifru.ifru_addr; 158 if (err == -1 || psa->sa_family != af) 159 continue; 160 err = ioctl(sockfd, SIOCGIFFLAGS, (void*)&ifr); 161 if (err == -1) 162 continue; 163 if (((ifr.ifr_flags & flags) != flags) || 164 ((ifr.ifr_flags & unflags) != 0)) 165 continue; 166 ifp = (interface_list_t*) malloc(sizeof(*ifp)); 167 if (ifp) { 168 strncpy(ifp->ifl_name, ifr.ifr_name, IFNAMSIZ); 169 memcpy(&ifp->ifl_addr, psa, sizeof(*psa)); 170 ifp->ifl_next = NULL; 171 if (list == NULL) 172 list = ifp; 173 if (ifprev != NULL) 174 ifprev->ifl_next = ifp; 175 ifprev = ifp; 176 } 177 } 178 close(sockfd); 179 return list; 180} 181 182/* 183 * void free_interface_list(interface_list_t *ifl) 184 * 185 * Free a list of interfaces 186 */ 187void free_interface_list(interface_list_t *ifl) 188{ 189 interface_list_t *ifp = ifl; 190 191 while (ifp) { 192 ifl = ifp; 193 ifp = ifp->ifl_next; 194 free(ifl); 195 } 196} 197 198/* 199 * short get_interface_flags(char *ifname) 200 * 201 * Get the value of the flags for a certain interface 202 */ 203short get_interface_flags(char *ifname) 204{ 205 struct ifreq ifr; 206 int sockfd, err; 207 208 sockfd = socket(PF_INET, SOCK_DGRAM, 0); 209 if (sockfd <= 0) 210 return -1; 211 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 212 err = ioctl(sockfd, SIOCGIFFLAGS, (void*)&ifr); 213 close(sockfd); 214 if (err == -1) 215 return -1; 216 return ifr.ifr_flags; 217} 218 219/* 220 * short set_interface_flags(char *ifname, short flags) 221 * 222 * Set the value of the flags for a certain interface 223 */ 224short set_interface_flags(char *ifname, short flags) 225{ 226 struct ifreq ifr; 227 int sockfd, err; 228 229 sockfd = socket(AF_INET, SOCK_DGRAM, 0); 230 //sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); 231 if (sockfd <= 0) 232 return -1; 233 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 234 ifr.ifr_flags = flags; 235 err = ioctl(sockfd, SIOCSIFFLAGS, (void*)&ifr); 236 close(sockfd); 237 if (err == -1) 238 return -1; 239 return 0; 240} 241 242/* 243 * short get_interface_flags(char *ifname) 244 * 245 * Get the value of the flags for a certain interface 246 */ 247int get_interface_mtu(char *ifname) 248{ 249 struct ifreq ifr; 250 int sockfd, err; 251 252 sockfd = socket(PF_INET, SOCK_DGRAM, 0); 253 if (sockfd <= 0) 254 return -1; 255 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 256 err = ioctl(sockfd, SIOCGIFMTU, (void*)&ifr); 257 close(sockfd); 258 if (err == -1) 259 return -1; 260 return ifr.ifr_mtu; 261} 262 263/* 264 * int mrouter_onoff(int sockfd, int onoff) 265 * 266 * Tell the kernel if a multicast router is on or off 267 */ 268int mrouter_onoff(int sockfd, int onoff) 269{ 270 int err, cmd, i; 271 272 cmd = (onoff) ? MRT_INIT : MRT_DONE; 273 i = 1; 274 err = setsockopt(sockfd, IPPROTO_IP, cmd, (void*)&i, sizeof(i)); 275 return err; 276} 277 278 279/* 280 * function name: wordToOption 281 * input: char *word, a pointer to the word 282 * output: int; a number corresponding to the code of the word 283 * operation: converts the result of the string comparisons into numerics. 284 * comments: called by config_vifs_from_file() 285 */ 286int 287wordToOption(char *word) 288{ 289 if (EQUAL(word, "")) 290 return EMPTY; 291 if (EQUAL(word, "igmpversion")) 292 return IGMPVERSION; 293 if (EQUAL(word, "is_querier")) 294 return IS_QUERIER; 295 if (EQUAL(word,"upstream")) 296 return UPSTREAM; 297 return UNKNOWN; 298} 299 300char * next_word(char **s) 301{ 302 char *w; 303 304 w = *s; 305 while (*w == ' ' || *w == '\t') 306 w++; 307 308 *s = w; 309 for(;;) { 310 switch (**s) { 311 case ' ' : 312 case '\t' : 313 **s = '\0'; 314 (*s)++; 315 return(w); 316 case '\n' : 317 case '#' : 318 **s = '\0'; 319 return(w); 320 case '\0' : 321 return(w); 322 default : 323 if (isascii(**s) && isupper(**s)) 324 **s = tolower(**s); 325 (*s)++; 326 } 327 } 328} 329