00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "dhcpd.h"
00036
00037 #if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING)
00038 #include "includes/netinet/ip.h"
00039 #include "includes/netinet/udp.h"
00040 #include "includes/netinet/if_ether.h"
00041 #endif
00042
00043
00044
00045 u_int32_t checksum (buf, nbytes, sum)
00046 unsigned char *buf;
00047 unsigned nbytes;
00048 u_int32_t sum;
00049 {
00050 unsigned i;
00051
00052 #ifdef DEBUG_CHECKSUM
00053 log_debug ("checksum (%x %d %x)", buf, nbytes, sum);
00054 #endif
00055
00056
00057 for (i = 0; i < (nbytes & ~1U); i += 2) {
00058 #ifdef DEBUG_CHECKSUM_VERBOSE
00059 log_debug ("sum = %x", sum);
00060 #endif
00061 sum += (u_int16_t) ntohs(*((u_int16_t *)(buf + i)));
00062
00063 if (sum > 0xFFFF)
00064 sum -= 0xFFFF;
00065 }
00066
00067
00068
00069 if (i < nbytes) {
00070 #ifdef DEBUG_CHECKSUM_VERBOSE
00071 log_debug ("sum = %x", sum);
00072 #endif
00073 sum += buf [i] << 8;
00074
00075 if (sum > 0xFFFF)
00076 sum -= 0xFFFF;
00077 }
00078
00079 return sum;
00080 }
00081
00082
00083
00084 u_int32_t wrapsum (sum)
00085 u_int32_t sum;
00086 {
00087 #ifdef DEBUG_CHECKSUM
00088 log_debug ("wrapsum (%x)", sum);
00089 #endif
00090
00091 sum = ~sum & 0xFFFF;
00092 #ifdef DEBUG_CHECKSUM_VERBOSE
00093 log_debug ("sum = %x", sum);
00094 #endif
00095
00096 #ifdef DEBUG_CHECKSUM
00097 log_debug ("wrapsum returns %x", htons (sum));
00098 #endif
00099 return htons(sum);
00100 }
00101
00102 #ifdef PACKET_ASSEMBLY
00103 void assemble_hw_header (interface, buf, bufix, to)
00104 struct interface_info *interface;
00105 unsigned char *buf;
00106 unsigned *bufix;
00107 struct hardware *to;
00108 {
00109 switch (interface->hw_address.hbuf[0]) {
00110 #if defined(HAVE_TR_SUPPORT)
00111 case HTYPE_IEEE802:
00112 assemble_tr_header(interface, buf, bufix, to);
00113 break;
00114 #endif
00115 #if defined (DEC_FDDI)
00116 case HTYPE_FDDI:
00117 assemble_fddi_header(interface, buf, bufix, to);
00118 break;
00119 #endif
00120 case HTYPE_INFINIBAND:
00121 log_error("Attempt to assemble hw header for infiniband");
00122 break;
00123 case HTYPE_ETHER:
00124 default:
00125 assemble_ethernet_header(interface, buf, bufix, to);
00126 break;
00127 }
00128 }
00129
00130
00131
00132 void assemble_udp_ip_header (interface, buf, bufix,
00133 from, to, port, data, len)
00134 struct interface_info *interface;
00135 unsigned char *buf;
00136 unsigned *bufix;
00137 u_int32_t from;
00138 u_int32_t to;
00139 u_int32_t port;
00140 unsigned char *data;
00141 unsigned len;
00142 {
00143 struct ip ip;
00144 struct udphdr udp;
00145
00146 memset (&ip, 0, sizeof ip);
00147
00148
00149 IP_V_SET (&ip, 4);
00150 IP_HL_SET (&ip, 20);
00151 ip.ip_tos = IPTOS_LOWDELAY;
00152 ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len);
00153 ip.ip_id = 0;
00154 ip.ip_off = 0;
00155 ip.ip_ttl = 128;
00156 ip.ip_p = IPPROTO_UDP;
00157 ip.ip_sum = 0;
00158 ip.ip_src.s_addr = from;
00159 ip.ip_dst.s_addr = to;
00160
00161
00162 ip.ip_sum = wrapsum (checksum ((unsigned char *)&ip, sizeof ip, 0));
00163
00164
00165 memcpy (&buf [*bufix], &ip, sizeof ip);
00166 *bufix += sizeof ip;
00167
00168
00169 udp.uh_sport = local_port;
00170 udp.uh_dport = port;
00171 udp.uh_ulen = htons(sizeof(udp) + len);
00172 memset (&udp.uh_sum, 0, sizeof udp.uh_sum);
00173
00174
00175
00176
00177 udp.uh_sum =
00178 wrapsum (checksum ((unsigned char *)&udp, sizeof udp,
00179 checksum (data, len,
00180 checksum ((unsigned char *)
00181 &ip.ip_src,
00182 2 * sizeof ip.ip_src,
00183 IPPROTO_UDP +
00184 (u_int32_t)
00185 ntohs (udp.uh_ulen)))));
00186
00187
00188 memcpy (&buf [*bufix], &udp, sizeof udp);
00189 *bufix += sizeof udp;
00190 }
00191 #endif
00192
00193 #ifdef PACKET_DECODING
00194
00195
00196
00197
00198
00199 ssize_t decode_hw_header (interface, buf, bufix, from)
00200 struct interface_info *interface;
00201 unsigned char *buf;
00202 unsigned bufix;
00203 struct hardware *from;
00204 {
00205 switch(interface->hw_address.hbuf[0]) {
00206 #if defined (HAVE_TR_SUPPORT)
00207 case HTYPE_IEEE802:
00208 return (decode_tr_header(interface, buf, bufix, from));
00209 #endif
00210 #if defined (DEC_FDDI)
00211 case HTYPE_FDDI:
00212 return (decode_fddi_header(interface, buf, bufix, from));
00213 #endif
00214 case HTYPE_INFINIBAND:
00215 log_error("Attempt to decode hw header for infiniband");
00216 return (0);
00217 case HTYPE_ETHER:
00218 default:
00219 return (decode_ethernet_header(interface, buf, bufix, from));
00220 }
00221 }
00222
00223
00224
00225 ssize_t
00226 decode_udp_ip_header(struct interface_info *interface,
00227 unsigned char *buf, unsigned bufix,
00228 struct sockaddr_in *from, unsigned buflen,
00229 unsigned *rbuflen, int nocsum)
00230 {
00231 unsigned char *data;
00232 struct ip ip;
00233 struct udphdr udp;
00234 unsigned char *upp, *endbuf;
00235 u_int32_t ip_len, ulen, pkt_len;
00236 u_int32_t sum, usum;
00237 static int ip_packets_seen;
00238 static int ip_packets_bad_checksum;
00239 static int udp_packets_seen;
00240 static int udp_packets_bad_checksum;
00241 static int udp_packets_length_checked;
00242 static int udp_packets_length_overflow;
00243 unsigned len;
00244
00245
00246 endbuf = buf + bufix + buflen;
00247
00248
00249 if ((buf + bufix + sizeof(ip)) > endbuf)
00250 return -1;
00251
00252
00253
00254
00255
00256 upp = buf + bufix;
00257 memcpy(&ip, upp, sizeof(ip));
00258 ip_len = (*upp & 0x0f) << 2;
00259 upp += ip_len;
00260
00261
00262 pkt_len = ntohs(ip.ip_len);
00263 if (pkt_len > buflen)
00264 return -1;
00265
00266
00267 if ((upp + sizeof(udp)) > endbuf)
00268 return -1;
00269
00270
00271 memcpy(&udp, upp, sizeof(udp));
00272
00273 #ifdef USERLAND_FILTER
00274
00275 if (ip.ip_p != IPPROTO_UDP)
00276 return -1;
00277
00278
00279 if (udp.uh_dport != local_port)
00280 return -1;
00281 #endif
00282
00283 ulen = ntohs(udp.uh_ulen);
00284 if (ulen < sizeof(udp))
00285 return -1;
00286
00287 udp_packets_length_checked++;
00288 if ((upp + ulen) > endbuf) {
00289 udp_packets_length_overflow++;
00290 if ((udp_packets_length_checked > 4) &&
00291 ((udp_packets_length_checked /
00292 udp_packets_length_overflow) < 2)) {
00293 log_info("%d udp packets in %d too long - dropped",
00294 udp_packets_length_overflow,
00295 udp_packets_length_checked);
00296 udp_packets_length_overflow = 0;
00297 udp_packets_length_checked = 0;
00298 }
00299 return -1;
00300 }
00301
00302 if ((ulen < sizeof(udp)) || ((upp + ulen) > endbuf))
00303 return -1;
00304
00305
00306 ++ip_packets_seen;
00307 if (wrapsum (checksum (buf + bufix, ip_len, 0))) {
00308 ++ip_packets_bad_checksum;
00309 if (ip_packets_seen > 4 &&
00310 (ip_packets_seen / ip_packets_bad_checksum) < 2) {
00311 log_info ("%d bad IP checksums seen in %d packets",
00312 ip_packets_bad_checksum, ip_packets_seen);
00313 ip_packets_seen = ip_packets_bad_checksum = 0;
00314 }
00315 return -1;
00316 }
00317
00318
00319 memcpy(&from->sin_addr, &ip.ip_src, 4);
00320
00321
00322
00323
00324
00325 data = upp + sizeof(udp);
00326 len = ulen - sizeof(udp);
00327
00328 usum = udp.uh_sum;
00329 if (usum == 0xffff) usum = 0;
00330 udp.uh_sum = 0;
00331
00332
00333
00334
00335 sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp),
00336 checksum(data, len,
00337 checksum((unsigned char *)&ip.ip_src,
00338 8, IPPROTO_UDP + ulen))));
00339
00340 udp_packets_seen++;
00341 if (!nocsum && usum && usum != sum) {
00342 udp_packets_bad_checksum++;
00343 if (udp_packets_seen > 4 &&
00344 (udp_packets_seen / udp_packets_bad_checksum) < 2) {
00345 log_info ("%d bad udp checksums in %d packets",
00346 udp_packets_bad_checksum, udp_packets_seen);
00347 udp_packets_seen = udp_packets_bad_checksum = 0;
00348 }
00349 return -1;
00350 }
00351
00352
00353 memcpy (&from -> sin_port, &udp.uh_sport, sizeof udp.uh_sport);
00354
00355
00356 if (rbuflen != NULL)
00357 *rbuflen = len;
00358
00359
00360 return ip_len + sizeof udp;
00361 }
00362 #endif