#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <features.h>
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <errno.h>
#include "packet.h"
#include "debug.h"
#include "dhcpd.h"
#include "options.h"
Include dependency graph for packet.c:
Go to the source code of this file.
Functions | |
void | init_header (struct dhcpMessage *packet, char type) |
int | get_packet (struct dhcpMessage *packet, int fd) |
u_int16_t | checksum (void *addr, int count) |
int | raw_packet (struct dhcpMessage *payload, u_int32_t source_ip, int source_port, u_int32_t dest_ip, int dest_port, unsigned char *dest_arp, int ifindex) |
int | kernel_packet (struct dhcpMessage *payload, u_int32_t source_ip, int source_port, u_int32_t dest_ip, int dest_port) |
u_int16_t checksum | ( | void * | addr, | |
int | count | |||
) |
Definition at line 88 of file packet.c.
Referenced by get_raw_packet(), and raw_packet().
00089 { 00090 /* Compute Internet Checksum for "count" bytes 00091 * beginning at location "addr". 00092 */ 00093 register int32_t sum = 0; 00094 u_int16_t *source = (u_int16_t *) addr; 00095 00096 while (count > 1) { 00097 /* This is the inner loop */ 00098 sum += *source++; 00099 count -= 2; 00100 } 00101 00102 /* Add left-over byte, if any */ 00103 if (count > 0) { 00104 /* Make sure that the left-over byte is added correctly both 00105 * with little and big endian hosts */ 00106 u_int16_t tmp = 0; 00107 *(unsigned char *) (&tmp) = * (unsigned char *) source; 00108 sum += tmp; 00109 } 00110 /* Fold 32-bit sum to 16 bits */ 00111 while (sum >> 16) 00112 sum = (sum & 0xffff) + (sum >> 16); 00113 00114 return ~sum; 00115 }
int get_packet | ( | struct dhcpMessage * | packet, | |
int | fd | |||
) |
Definition at line 47 of file packet.c.
References BOOTREQUEST, BROADCAST_FLAG, dhcpMessage::cookie, DEBUG, DHCP_MAGIC, DHCP_VENDOR, dhcpMessage::flags, LOG, LOG_ERR, LOG_INFO, dhcpMessage::op, and OPT_LEN.
Referenced by udhcp().
00048 { 00049 int bytes; 00050 int i; 00051 const char broken_vendors[][8] = { 00052 "MSFT 98", 00053 "" 00054 }; 00055 char unsigned *vendor; 00056 00057 memset(packet, 0, sizeof(struct dhcpMessage)); 00058 bytes = read(fd, packet, sizeof(struct dhcpMessage)); 00059 if (bytes < 0) { 00060 00061 DEBUG(LOG_INFO, "couldn't read on listening socket, ignoring"); 00062 return -1; 00063 } 00064 00065 if (ntohl(packet->cookie) != DHCP_MAGIC) { 00066 LOG(LOG_ERR, "received bogus message, ignoring"); 00067 return -2; 00068 } 00069 00070 DEBUG(LOG_INFO, "Received a packet"); 00071 00072 if (packet->op == BOOTREQUEST && (vendor = get_option(packet, DHCP_VENDOR))) { 00073 for (i = 0; broken_vendors[i][0]; i++) { 00074 if (vendor[OPT_LEN - 2] == (unsigned char) strlen(broken_vendors[i]) && 00075 !strncmp(vendor, broken_vendors[i], vendor[OPT_LEN - 2])) { 00076 DEBUG(LOG_INFO, "broken client (%s), forcing broadcast", 00077 broken_vendors[i]); 00078 packet->flags |= htons(BROADCAST_FLAG); 00079 } 00080 } 00081 } 00082 00083 00084 return bytes; 00085 }
void init_header | ( | struct dhcpMessage * | packet, | |
char | type | |||
) |
Definition at line 23 of file packet.c.
References BOOTREPLY, BOOTREQUEST, dhcpMessage::cookie, DHCP_END, DHCP_MAGIC, DHCP_MESSAGE_TYPE, DHCPACK, DHCPDISCOVER, DHCPINFORM, DHCPNAK, DHCPOFFER, DHCPRELEASE, DHCPREQUEST, ETH_10MB, ETH_10MB_LEN, dhcpMessage::hlen, dhcpMessage::htype, dhcpMessage::op, and dhcpMessage::options.
00024 { 00025 memset(packet, 0, sizeof(struct dhcpMessage)); 00026 switch (type) { 00027 case DHCPDISCOVER: 00028 case DHCPREQUEST: 00029 case DHCPRELEASE: 00030 case DHCPINFORM: 00031 packet->op = BOOTREQUEST; 00032 break; 00033 case DHCPOFFER: 00034 case DHCPACK: 00035 case DHCPNAK: 00036 packet->op = BOOTREPLY; 00037 } 00038 packet->htype = ETH_10MB; 00039 packet->hlen = ETH_10MB_LEN; 00040 packet->cookie = htonl(DHCP_MAGIC); 00041 packet->options[0] = DHCP_END; 00042 add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type); 00043 }
int kernel_packet | ( | struct dhcpMessage * | payload, | |
u_int32_t | source_ip, | |||
int | source_port, | |||
u_int32_t | dest_ip, | |||
int | dest_port | |||
) |
Definition at line 174 of file packet.c.
Referenced by send_release(), and send_renew().
00176 { 00177 int n = 1; 00178 int fd, result; 00179 struct sockaddr_in client; 00180 00181 if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 00182 return -1; 00183 00184 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1) 00185 return -1; 00186 00187 memset(&client, 0, sizeof(client)); 00188 client.sin_family = AF_INET; 00189 client.sin_port = htons(source_port); 00190 client.sin_addr.s_addr = source_ip; 00191 00192 if (bind(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1) 00193 return -1; 00194 00195 memset(&client, 0, sizeof(client)); 00196 client.sin_family = AF_INET; 00197 client.sin_port = htons(dest_port); 00198 client.sin_addr.s_addr = dest_ip; 00199 00200 if (connect(fd, (struct sockaddr *)&client, sizeof(struct sockaddr)) == -1) 00201 return -1; 00202 00203 result = write(fd, payload, sizeof(struct dhcpMessage)); 00204 close(fd); 00205 00206 return result; 00207 }
int raw_packet | ( | struct dhcpMessage * | payload, | |
u_int32_t | source_ip, | |||
int | source_port, | |||
u_int32_t | dest_ip, | |||
int | dest_port, | |||
unsigned char * | dest_arp, | |||
int | ifindex | |||
) |
Definition at line 119 of file packet.c.
References checksum(), DEBUG, and LOG_ERR.
Referenced by send_discover(), send_renew(), and send_selecting().
00121 { 00122 int fd; 00123 int result; 00124 struct sockaddr_ll dest; 00125 struct udp_dhcp_packet packet; 00126 00127 if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { 00128 00129 DEBUG(LOG_ERR, "socket call failed: %s", strerror(errno)); 00130 return -1; 00131 } 00132 00133 memset(&dest, 0, sizeof(dest)); 00134 memset(&packet, 0, sizeof(packet)); 00135 00136 dest.sll_family = AF_PACKET; 00137 dest.sll_protocol = htons(ETH_P_IP); 00138 dest.sll_ifindex = ifindex; 00139 dest.sll_halen = 6; 00140 memcpy(dest.sll_addr, dest_arp, 6); 00141 if (bind(fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_ll)) < 0) { 00142 DEBUG(LOG_ERR, "bind call failed: %s", strerror(errno)); 00143 close(fd); 00144 return -1; 00145 } 00146 00147 packet.ip.protocol = IPPROTO_UDP; 00148 packet.ip.saddr = source_ip; 00149 packet.ip.daddr = dest_ip; 00150 packet.udp.source = htons(source_port); 00151 packet.udp.dest = htons(dest_port); 00152 packet.udp.len = htons(sizeof(packet.udp) + sizeof(struct dhcpMessage)); /* cheat on the psuedo-header */ 00153 packet.ip.tot_len = packet.udp.len; 00154 memcpy(&(packet.data), payload, sizeof(struct dhcpMessage)); 00155 packet.udp.check = checksum(&packet, sizeof(struct udp_dhcp_packet)); 00156 00157 packet.ip.tot_len = htons(sizeof(struct udp_dhcp_packet)); 00158 packet.ip.ihl = sizeof(packet.ip) >> 2; 00159 packet.ip.version = IPVERSION; 00160 packet.ip.ttl = IPDEFTTL; 00161 packet.ip.check = checksum(&(packet.ip), sizeof(packet.ip)); 00162 00163 result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, (struct sockaddr *) &dest, sizeof(dest)); 00164 if (result <= 0) { 00165 00166 DEBUG(LOG_ERR, "write on socket failed: %s", strerror(errno)); 00167 } 00168 close(fd); 00169 return result; 00170 }
Here is the call graph for this function: