1/* 2 * Copyright 2004, Broadcom Corporation 3 * All Rights Reserved. 4 * 5 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 6 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 7 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 8 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 9 * 10 * $Id: linux_osl.c,v 1.1.1.1 2008/10/15 03:31:35 james26_jang Exp $ 11 */ 12 13#include <sys/ioctl.h> 14#include <net/if.h> 15#include <linux/socket.h> 16 17#include "upnp_osl.h" 18#include "upnp_dbg.h" 19#include "upnp.h" 20 21 22struct in_addr *osl_ifaddr(const char *ifname, struct in_addr *inaddr) 23{ 24 int sockfd; 25 struct ifreq ifreq; 26 27 if ((sockfd = socket( AF_INET, SOCK_DGRAM, 0 )) < 0) { 28 perror("socket"); 29 return NULL; 30 } 31 32 strncpy(ifreq.ifr_name, ifname, IFNAMSIZ); 33 if (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0) { 34 inaddr = NULL; 35 } else { 36 memcpy(inaddr, &(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr), sizeof(struct in_addr)); 37 } 38 close(sockfd); 39 return inaddr; 40} 41 42 43 44int osl_join_multicast(struct iface *pif, int fd, ulong ipaddr, ushort port) 45{ 46 struct ip_mreqn mcreqn; 47 struct ifreq ifreq; 48 struct sockaddr_in mcaddr; 49 int success = FALSE; 50 int flag; 51 52 do { 53 54 // make sure this interface is capable of MULTICAST... 55 memset(&ifreq, 0, sizeof(ifreq)); 56 strcpy(ifreq.ifr_name, pif->ifname); 57 if (ioctl(fd, SIOCGIFFLAGS, (int) &ifreq)) 58 break; 59 60 if ((ifreq.ifr_flags & IFF_MULTICAST) == 0) 61 break; 62 63 // bind the socket to an address and port. 64 flag = 1; 65 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &flag, sizeof(flag)); 66 67 memset(&mcaddr, 0, sizeof(mcaddr)); 68 // memcpy(&mcaddr.sin_addr, &pif->inaddr, sizeof(mcaddr.sin_addr)); 69 mcaddr.sin_addr.s_addr = htonl( INADDR_ANY ); 70 mcaddr.sin_family = AF_INET; 71 mcaddr.sin_port = htons(port); 72 if ( bind(fd, (struct sockaddr *) &mcaddr, sizeof(mcaddr)) ) 73 break; 74 75 // join the multicast group. 76 memset(&ifreq, 0, sizeof(ifreq)); 77 strcpy(ifreq.ifr_name, pif->ifname); 78 if (ioctl(fd, SIOCGIFINDEX, &ifreq)) 79 break; 80 81 memset(&mcreqn, 0, sizeof(mcreqn)); 82 mcreqn.imr_multiaddr.s_addr = ipaddr; 83 //mcreqn.imr_interface.s_addr = mcaddr.sin_addr.s_addr; 84 // if we get to use struct ip_mreqn, delete the previous line and uncomment the next two 85 mcreqn.imr_address.s_addr = mcaddr.sin_addr.s_addr; 86 mcreqn.imr_ifindex = ifreq.ifr_ifindex; 87 if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcreqn, sizeof(mcreqn))) 88 break; 89 90 // restrict multicast messages sent on this socket 91 // to only go out this interface and no other 92 // (doesn't say anything about multicast receives.) 93 // 94 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*) &pif->inaddr, sizeof(pif->inaddr))) 95 break; 96 97 success = TRUE; 98 99 } while (0); 100 101 // TRUE == success, FALSE otherwise. 102 return success; 103} 104 105 106char * 107safe_snprintf(char *str, int *len, const char *fmt, ...) 108{ 109 va_list ap; 110 int n; 111 112 va_start(ap, fmt); 113 n = vsnprintf(str, *len, fmt, ap); 114 va_end(ap); 115 116 if (n > 0) { 117 str += n; 118 *len -= n; 119 } else if (n < 0) { 120 *len = 0; 121 } 122 123 return str; 124} 125