1/* vi: set sw=4 ts=4: */ 2/* 3 * socket.c -- DHCP server client/server socket creation 4 * 5 * udhcp client/server 6 * Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au> 7 * Chris Trew <ctrew@moreton.com.au> 8 * 9 * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 */ 25 26#include <net/if.h> 27#include <features.h> 28#if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined \ 29 _NEWLIB_VERSION 30#include <netpacket/packet.h> 31#include <net/ethernet.h> 32#else 33#include <asm/types.h> 34#include <linux/if_packet.h> 35#include <linux/if_ether.h> 36#endif 37 38#include "common.h" 39 40 41int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t *arp) 42{ 43 int fd; 44 struct ifreq ifr; 45 struct sockaddr_in *our_ip; 46 47 memset(&ifr, 0, sizeof(ifr)); 48 fd = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW); 49 50 ifr.ifr_addr.sa_family = AF_INET; 51 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)); 52 if (addr) { 53 if (ioctl_or_perror(fd, SIOCGIFADDR, &ifr, 54 "is interface %s up and configured?", interface) 55 ) { 56 close(fd); 57 return -1; 58 } 59 our_ip = (struct sockaddr_in *) &ifr.ifr_addr; 60 *addr = our_ip->sin_addr.s_addr; 61 DEBUG("%s (our ip) = %s", ifr.ifr_name, inet_ntoa(our_ip->sin_addr)); 62 } 63 64 if (ifindex) { 65 if (ioctl_or_warn(fd, SIOCGIFINDEX, &ifr) != 0) { 66 close(fd); 67 return -1; 68 } 69 DEBUG("adapter index %d", ifr.ifr_ifindex); 70 *ifindex = ifr.ifr_ifindex; 71 } 72 73 if (arp) { 74 if (ioctl_or_warn(fd, SIOCGIFHWADDR, &ifr) != 0) { 75 close(fd); 76 return -1; 77 } 78 memcpy(arp, ifr.ifr_hwaddr.sa_data, 6); 79 DEBUG("adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x", 80 arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]); 81 } 82 83 close(fd); 84 return 0; 85} 86 87/* 1. None of the callers expects it to ever fail */ 88/* 2. ip was always INADDR_ANY */ 89int listen_socket(/*uint32_t ip,*/ int port, const char *inf) 90{ 91 int fd; 92 struct ifreq interface; 93 struct sockaddr_in addr; 94 95 DEBUG("Opening listen socket on *:%d %s", port, inf); 96 fd = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 97 98 setsockopt_reuseaddr(fd); 99 if (setsockopt_broadcast(fd) == -1) 100 bb_perror_msg_and_die("SO_BROADCAST"); 101 102 strncpy(interface.ifr_name, inf, IFNAMSIZ); 103 if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, sizeof(interface)) == -1) 104 bb_perror_msg_and_die("SO_BINDTODEVICE"); 105 106 memset(&addr, 0, sizeof(addr)); 107 addr.sin_family = AF_INET; 108 addr.sin_port = htons(port); 109 /* addr.sin_addr.s_addr = ip; - all-zeros is INADDR_ANY */ 110 xbind(fd, (struct sockaddr *)&addr, sizeof(addr)); 111 112 return fd; 113} 114