1/* vi: set sw=4 ts=4: */ 2/* 3 * 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#include "common.h" 26#include <net/if.h> 27 28int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex, 29 uint32_t *nip, uint8_t *mac, uint16_t *mtu) 30{ 31 /* char buffer instead of bona-fide struct avoids aliasing warning */ 32 char ifr_buf[sizeof(struct ifreq)]; 33 struct ifreq *const ifr = (void *)ifr_buf; 34 35 int fd; 36 struct sockaddr_in *our_ip; 37 38 memset(ifr, 0, sizeof(*ifr)); 39 fd = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW); 40 41 ifr->ifr_addr.sa_family = AF_INET; 42 strncpy_IFNAMSIZ(ifr->ifr_name, interface); 43 if (nip) { 44 if (ioctl_or_perror(fd, SIOCGIFADDR, ifr, 45 "is interface %s up and configured?", interface) 46 ) { 47 close(fd); 48 return -1; 49 } 50 our_ip = (struct sockaddr_in *) &ifr->ifr_addr; 51 *nip = our_ip->sin_addr.s_addr; 52 log1("IP %s", inet_ntoa(our_ip->sin_addr)); 53 } 54 55 if (ifindex) { 56 if (ioctl_or_warn(fd, SIOCGIFINDEX, ifr) != 0) { 57 close(fd); 58 return -1; 59 } 60 log1("Adapter index %d", ifr->ifr_ifindex); 61 *ifindex = ifr->ifr_ifindex; 62 } 63 64 if (mac) { 65 if (ioctl_or_warn(fd, SIOCGIFHWADDR, ifr) != 0) { 66 close(fd); 67 return -1; 68 } 69 memcpy(mac, ifr->ifr_hwaddr.sa_data, 6); 70 log1("MAC %02x:%02x:%02x:%02x:%02x:%02x", 71 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 72 } 73 74 if (mtu) { 75 if (ioctl_or_warn(fd, SIOCGIFMTU, ifr) != 0) { 76 close(fd); 77 return -1; 78 } 79 log1("Adapter mtu %d", ifr->ifr_mtu); 80 *mtu = ifr->ifr_mtu; 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 FAST_FUNC udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) 90{ 91 int fd; 92 struct sockaddr_in addr; 93 char *colon; 94 95 log1("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 /* SO_BINDTODEVICE doesn't work on ethernet aliases (ethN:M) */ 103 colon = strrchr(inf, ':'); 104 if (colon) 105 *colon = '\0'; 106 107 if (setsockopt_bindtodevice(fd, inf)) 108 xfunc_die(); /* warning is already printed */ 109 110 if (colon) 111 *colon = ':'; 112 113 memset(&addr, 0, sizeof(addr)); 114 addr.sin_family = AF_INET; 115 addr.sin_port = htons(port); 116 /* addr.sin_addr.s_addr = ip; - all-zeros is INADDR_ANY */ 117 xbind(fd, (struct sockaddr *)&addr, sizeof(addr)); 118 119 return fd; 120} 121