Package: l2tpns Version: 2.1.10rem-4 Severity: important Tags: patch
Trying to setup a ipsec/l2tp connection from a Windows XP client to a SPARC server I always get bus errors from l2tpns. This makes the package totally unusable on SPARC. I did some digging around and have determined that the bus errors are caused by unaligned memory accesses (SPARC requires that 2 byte accesses are 2 byte aligned, 4 byte are 4 and 8 byte are 8). I enclose a patch which replaces all direct casts with uses of get_unalignedxx and put_unalignedxx macros. On the SPARC platform these macros call local functions that do bytewise copying but on other platforms they do the original direct accesses. In cases where large structures need aligning the patch defines stack copies of the data and uses memcpy to transfer the data to/from the network buffers. There are a couple of places where I'm not sure if data should be converted to network byte order. I have marked these with FIXME in the patch. Note most seem to affect clustering so all should be ok if l2tpns is run on a homogeneous set of servers. Finally is also added -Wcast-align to the gcc command line. This causes the compiler to warn where potential misalignments are. I added some extra (void*) casts to get rid of what seem to be false warnings. The patch has only been tested on sparc64 and allows me to connect my Windows XP machine using l2tp. Regards Richard -- System Information: Debian Release: testing/unstable APT prefers unstable APT policy: (500, 'unstable'), (500, 'testing') Architecture: sparc (sparc64) Shell: /bin/sh linked to /bin/bash Kernel: Linux 2.6.12-1-sparc64 Locale: LANG=en_GB, LC_CTYPE=en_GB (charmap=ISO-8859-1) Versions of packages l2tpns depends on: ii libc6 2.3.5-8 GNU C Library: Shared libraries an ii libcli1 1.8.5-1 emulates a cisco style telnet comm l2tpns recommends no packages. -- no debconf information
diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/autosnoop.c l2tpns-2.1.10/autosnoop.c --- l2tpns-2.1.10.orig/l2tpns-2.1.10/autosnoop.c 2005-10-11 10:04:53.000000000 +0100 +++ l2tpns-2.1.10/autosnoop.c 2005-11-26 23:02:14.000000000 +0000 @@ -1,6 +1,7 @@ #include <string.h> #include "l2tpns.h" #include "plugin.h" +#include "unaligned.h" /* set up intercept based on RADIUS reply */ @@ -57,7 +58,7 @@ uint8_t *p = *data->packet; *p = 26; // vendor-specific - *(uint32_t *) (p + 2) = htonl(9); // Cisco + put_unaligned32((p + 2), htonl(9)); // Cisco p[6] = 1; // Cisco-AVPair p[7] = 2 + sprintf((char *) p + 8, "intercept=%s:%d", f->fmtaddr(data->s->snoop_ip, 0), data->s->snoop_port); diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/autothrottle.c l2tpns-2.1.10/autothrottle.c --- l2tpns-2.1.10.orig/l2tpns-2.1.10/autothrottle.c 2005-10-11 10:04:53.000000000 +0100 +++ l2tpns-2.1.10/autothrottle.c 2005-11-26 23:02:14.000000000 +0000 @@ -1,6 +1,7 @@ #include <string.h> #include "l2tpns.h" #include "plugin.h" +#include "unaligned.h" /* set up throttling based on RADIUS reply */ @@ -123,7 +124,7 @@ if (data->s->throttle_in) { *p = 26; // vendor-specific - *(uint32_t *) (p + 2) = htonl(9); // Cisco + put_unaligned32((p + 2), htonl(9)); // Cisco p[6] = 1; // Cisco-AVPair p[7] = 2 + sprintf((char *) p + 8, "lcp:interface-config#%d=service-policy input %d", i++, @@ -136,7 +137,7 @@ if (data->s->throttle_out) { *p = 26; // vendor-specific - *(uint32_t *) (p + 2) = htonl(9); // Cisco + put_unaligned32((p + 2), htonl(9)); // Cisco p[6] = 1; // Cisco-AVPair p[7] = 2 + sprintf((char *) p + 8, "lcp:interface-config#%d=service-policy output %d", i++, diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/cli.c l2tpns-2.1.10/cli.c --- l2tpns-2.1.10.orig/l2tpns-2.1.10/cli.c 2005-09-01 07:59:06.000000000 +0100 +++ l2tpns-2.1.10/cli.c 2005-11-26 23:02:24.000000000 +0000 @@ -3079,11 +3079,21 @@ } // Convert a string in the form of abcd.ef12.3456 into char[6] -void parsemac(char *string, char mac[6]) +void parsemac(char *string, char macbytes[6]) { - if (sscanf(string, "%02x%02x.%02x%02x.%02x%02x", (unsigned int *)&mac[0], (unsigned int *)&mac[1], (unsigned int *)&mac[2], (unsigned int *)&mac[3], (unsigned int *)&mac[4], (unsigned int *)&mac[5]) == 6) + int mac[6]; + if (sscanf(string, "%02x%02x.%02x%02x.%02x%02x", (unsigned int *)&mac[0], (unsigned int *)&mac[1], (unsigned int *)&mac[2], (unsigned int *)&mac[3], (unsigned int *)&mac[4], (unsigned int *)&mac[5]) == 6) { + /* Empty */ + } else if (sscanf(string, "%02x%02x:%02x%02x:%02x%02x", (unsigned int *)&mac[0], (unsigned int *)&mac[1], (unsigned int *)&mac[2], (unsigned int *)&mac[3], (unsigned int *)&mac[4], (unsigned int *)&mac[5]) == 6) { + /* Empty */ + } else { + memset(macbytes, 0, 6); return; - if (sscanf(string, "%02x%02x:%02x%02x:%02x%02x", (unsigned int *)&mac[0], (unsigned int *)&mac[1], (unsigned int *)&mac[2], (unsigned int *)&mac[3], (unsigned int *)&mac[4], (unsigned int *)&mac[5]) == 6) - return; - memset(mac, 0, 6); + } + macbytes[0] = mac[0]; + macbytes[1] = mac[1]; + macbytes[2] = mac[2]; + macbytes[3] = mac[3]; + macbytes[4] = mac[4]; + macbytes[5] = mac[5]; } diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/cluster.c l2tpns-2.1.10/cluster.c --- l2tpns-2.1.10.orig/l2tpns-2.1.10/cluster.c 2005-11-04 14:41:50.000000000 +0000 +++ l2tpns-2.1.10/cluster.c 2005-12-01 22:17:35.000000000 +0000 @@ -23,6 +23,7 @@ #include "cluster.h" #include "util.h" #include "tbf.h" +#include "unaligned.h" #ifdef BGP #include "bgp.h" @@ -189,10 +190,11 @@ // static void add_type(uint8_t **p, int type, int more, uint8_t *data, int size) { - *((uint32_t *) (*p)) = type; + // FIXME do these need converting to network byte order? + put_unaligned32((*p), type); *p += sizeof(uint32_t); - *((uint32_t *)(*p)) = more; + put_unaligned32((*p), more); *p += sizeof(uint32_t); if (data && size > 0) { @@ -999,7 +1001,7 @@ // We've heard from another peer! Add it to the list // that we select from at election time. // -static int cluster_add_peer(in_addr_t peer, time_t basetime, pingt *pp, int size) +static int cluster_add_peer(in_addr_t peer, time_t basetime, uint8_t *pp, int size) { int i; in_addr_t clusterid; @@ -1110,9 +1112,8 @@ // static int cluster_handle_bytes(uint8_t *data, int size) { - bytest *b; - - b = (bytest *) data; + bytest myb; + bytest *b = &myb; LOG(3, 0, 0, "Got byte counter update (size %d)\n", size); @@ -1120,6 +1121,8 @@ counts to each of the sessions. */ while (size >= sizeof(*b) ) { + memcpy(&myb, data, sizeof(bytest)); + if (b->sid > MAXSESSION) { LOG(0, 0, 0, "Got C_BYTES with session #%d!\n", b->sid); return -1; /* Abort processing */ @@ -1138,7 +1141,7 @@ session[b->sid].last_packet = time_now; // Reset idle timer! size -= sizeof(*b); - ++b; + data += sizeof(*b); } if (size != 0) @@ -1165,7 +1168,7 @@ } } - load_session(more, (sessiont *) p); // Copy session into session table.. + load_session(more, p); // Copy session into session table.. LOG(5, more, 0, "Received session update (%d undef)\n", config->cluster_undefined_sessions); @@ -1258,11 +1261,14 @@ char reserved[18]; }; -static uint8_t *convert_session(struct oldsession *old) +static uint8_t *convert_session(uint8_t *oldp) { static sessiont new; + struct oldsession myold; + struct oldsession *old = &myold; int i; + memcpy(&myold, oldp, sizeof(myold)); memset(&new, 0, sizeof(new)); new.next = old->next; @@ -1334,7 +1340,8 @@ // v5: added ipv6, re-ordered session structure static int cluster_process_heartbeat(uint8_t *data, int size, int more, uint8_t *p, in_addr_t addr) { - heartt *h; + heartt myh; + heartt *h = &myh; int s = size - (p-data); int i, type; int hb_ver = more; @@ -1353,7 +1360,7 @@ if (s < sizeof(*h)) goto shortpacket; - h = (heartt *) p; + memcpy(h, p, sizeof(heartt)); p += sizeof(*h); s -= sizeof(*h); @@ -1484,11 +1491,12 @@ // Ok. process the packet... while ( s > 0) { - type = *((uint32_t *) p); + // FIXME do these need converting from network byte order??? + type = get_unaligned32(p); p += sizeof(uint32_t); s -= sizeof(uint32_t); - more = *((uint32_t *) p); + more = get_unaligned32(p); p += sizeof(uint32_t); s -= sizeof(uint32_t); @@ -1509,7 +1517,7 @@ // Now what? Should exit! No-longer up to date! break; } - cluster_recv_session(more, convert_session((struct oldsession *) c)); + cluster_recv_session(more, convert_session(c)); break; } @@ -1528,7 +1536,7 @@ if (s < sizeof(struct oldsession)) goto shortpacket; - cluster_recv_session(more, convert_session((struct oldsession *) p)); + cluster_recv_session(more, convert_session(p)); p += sizeof(struct oldsession); s -= sizeof(struct oldsession); @@ -1615,18 +1623,19 @@ if (s < 8) goto shortpacket; - type = *((uint32_t *) p); + // FIXME do these need converting from network byte order? + type = get_unaligned32(p); p += sizeof(uint32_t); s -= sizeof(uint32_t); - more = *((uint32_t *) p); + more = get_unaligned32(p); p += sizeof(uint32_t); s -= sizeof(uint32_t); switch (type) { case C_PING: // Update the peers table. - return cluster_add_peer(addr, more, (pingt *) p, s); + return cluster_add_peer(addr, more, p, s); case C_MASTER: // Our master is wrong return cluster_set_master(addr, more); @@ -1648,7 +1657,9 @@ struct sockaddr_in a; a.sin_addr.s_addr = more; - a.sin_port = *(int *) p; + // FIXME does this need converting from network byte + // order? + a.sin_port = get_unaligned32(p); s -= sizeof(int); p += sizeof(int); diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/icmp.c l2tpns-2.1.10/icmp.c --- l2tpns-2.1.10.orig/l2tpns-2.1.10/icmp.c 2005-08-10 12:25:56.000000000 +0100 +++ l2tpns-2.1.10/icmp.c 2005-11-26 23:41:08.000000000 +0000 @@ -17,6 +17,7 @@ #include <memory.h> #include "l2tpns.h" +#include "unaligned.h" static uint16_t _checksum(uint8_t *addr, int count); @@ -31,8 +32,10 @@ void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, uint8_t *packet, int packet_len) { char buf[128] = {0}; - struct iphdr *iph; - struct icmphdr *icmp; + struct iphdr myiph; + struct iphdr *iph = &myiph; + struct icmphdr myicmp; + struct icmphdr *icmp = &myicmp; int len = 0, on = 1, icmp_socket; struct sockaddr_in whereto = {0}; @@ -44,9 +47,9 @@ whereto.sin_addr.s_addr = destination; whereto.sin_family = AF_INET; - iph = (struct iphdr *)(buf); + memcpy(iph, buf, sizeof(struct iphdr)); len = sizeof(struct iphdr); - icmp = (struct icmphdr *)(buf + len); + memcpy(icmp, buf + len, sizeof(struct icmphdr)); len += sizeof(struct icmphdr); /* ip header + first 8 bytes of payload */ @@ -86,7 +89,7 @@ for (; count > 1; count -= 2) { - sum += ntohs(*(uint32_t *) addr); + sum += ntohs(get_unaligned32(addr)); addr += 2; } @@ -104,8 +107,10 @@ void send_ipv6_ra(sessionidt s, tunnelidt t, struct in6_addr *ip) { - struct nd_opt_prefix_info *pinfo; - struct ipv6_pseudo_hdr *phdr; + struct nd_opt_prefix_info mypinfo; + struct nd_opt_prefix_info *pinfo = &mypinfo; + struct ipv6_pseudo_hdr myphdr; + struct ipv6_pseudo_hdr *phdr = &myphdr; uint8_t b[MAXETHER + 20]; uint8_t c[MAXETHER + 20]; int l; @@ -146,9 +151,9 @@ *(o+44) = 64; // Hop count *(o+45) = 0; // Flags *(o+46) = *(o+47) = 255; // Lifetime - *(uint32_t *)(o+48) = 0; // Reachable time - *(uint32_t *)(o+52) = 0; // Retrans timer - pinfo = (struct nd_opt_prefix_info *)(o+56); + put_unaligned32((o+48), 0); // Reachable time + put_unaligned32((o+52), 0); // Retrans timer + memcpy(pinfo, o+56, sizeof(struct nd_opt_prefix_info)); pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; pinfo->nd_opt_pi_len = 4; pinfo->nd_opt_pi_prefix_len = 64; // prefix length @@ -161,7 +166,7 @@ l = sizeof(*pinfo) + 56; memset(c, 0, sizeof(c)); - phdr = (struct ipv6_pseudo_hdr *) c; + memcpy(phdr, c, sizeof(struct ipv6_pseudo_hdr)); memcpy(&phdr->src, o+8, 16); memcpy(&phdr->dest, o+24, 16); phdr->ulp_length = htonl(l - 40); @@ -170,7 +175,7 @@ memcpy(c + sizeof(*phdr), o + 40, l - 40); // Checksum is over the icmp6 payload plus the pseudo header - *(uint16_t *)(o+42) = _checksum(c, l - 40 + sizeof(*phdr)); + put_unaligned16((o+42), _checksum(c, l - 40 + sizeof(*phdr))); tunnelsend(b, l + (o-b), t); // send it... return; diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/l2tpns.c l2tpns-2.1.10/l2tpns.c --- l2tpns-2.1.10.orig/l2tpns-2.1.10/l2tpns.c 2005-11-04 14:41:50.000000000 +0000 +++ l2tpns-2.1.10/l2tpns.c 2005-11-30 23:34:16.000000000 +0000 @@ -49,6 +49,7 @@ #include "control.h" #include "util.h" #include "tbf.h" +#include "unaligned.h" #ifdef BGP #include "bgp.h" @@ -417,11 +418,11 @@ memset(&r, 0, sizeof(r)); r.rt_dev = config->tundevice; r.rt_dst.sa_family = AF_INET; - *(uint32_t *) & (((struct sockaddr_in *) &r.rt_dst)->sin_addr.s_addr) = htonl(ip); + put_unaligned32(& (((struct sockaddr_in *) ((void *)&r.rt_dst))->sin_addr.s_addr), htonl(ip)); r.rt_gateway.sa_family = AF_INET; - *(uint32_t *) & (((struct sockaddr_in *) &r.rt_gateway)->sin_addr.s_addr) = htonl(gw); + put_unaligned32(& (((struct sockaddr_in *) ((void *)&r.rt_gateway))->sin_addr.s_addr), htonl(gw)); r.rt_genmask.sa_family = AF_INET; - *(uint32_t *) & (((struct sockaddr_in *) &r.rt_genmask)->sin_addr.s_addr) = htonl(mask); + put_unaligned32(& (((struct sockaddr_in *) ((void *)&r.rt_genmask))->sin_addr.s_addr), htonl(mask)); r.rt_flags = (RTF_UP | RTF_STATIC); if (gw) r.rt_flags |= RTF_GATEWAY; @@ -669,9 +670,9 @@ uint8_t *a = (uint8_t *) &ip; uint8_t **d = (uint8_t **) ip_hash; - if (!(d = (uint8_t **) d[(size_t) *a++])) return 0; - if (!(d = (uint8_t **) d[(size_t) *a++])) return 0; - if (!(d = (uint8_t **) d[(size_t) *a++])) return 0; + if (!(d = (uint8_t **) ((void *) d[(size_t) *a++]))) return 0; + if (!(d = (uint8_t **) ((void *) d[(size_t) *a++]))) return 0; + if (!(d = (uint8_t **) ((void *) d[(size_t) *a++]))) return 0; return (int) (intptr_t) d[(size_t) *a]; } @@ -724,7 +725,7 @@ ip.s6_addr16[1] == 0 && ip.s6_addr16[2] == 0 && ip.s6_addr16[3] == 0)) { - s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]); + s = lookup_ipmap(get_unalignedin(&ip.s6_addr[8])); } else { s = lookup_ipv6map(ip); } @@ -756,7 +757,7 @@ return; } - d = (uint8_t **) d[(size_t) a[i]]; + d = (uint8_t **) ((void *) d[(size_t) a[i]]); } d[(size_t) a[3]] = (uint8_t *) (intptr_t) s; @@ -828,17 +829,17 @@ { if (!d[i]) continue; - e = (char **) d[i]; + e = (char **) ((void *) d[i]); for (j = 0; j < 256; ++j) { if (!e[j]) continue; - f = (char **) e[j]; + f = (char **) ((void *) e[j]); for (k = 0; k < 256; ++k) { if (!f[k]) continue; - g = (char **)f[k]; + g = (char **) ((void *) f[k]); for (l = 0; l < 256; ++l) { if (!g[l]) @@ -955,7 +956,7 @@ addr.sin_port = htons(tunnel[t].port); // sequence expected, if sequence in message - if (*buf & 0x08) *(uint16_t *) (buf + ((*buf & 0x40) ? 10 : 8)) = htons(tunnel[t].nr); + if (*buf & 0x08) put_unaligned16((buf + ((*buf & 0x40) ? 10 : 8)), htons(tunnel[t].nr)); // If this is a control message, deal with retries if (*buf & 0x80) @@ -971,7 +972,7 @@ if (sendto(udpfd, buf, l, 0, (void *) &addr, sizeof(addr)) < 0) { - LOG(0, ntohs((*(uint16_t *) (buf + 6))), t, "Error sending data out tunnel: %s (udpfd=%d, buf=%p, len=%d, dest=%s)\n", + LOG(0, ntohs(get_unaligned16(buf + 6)), t, "Error sending data out tunnel: %s (udpfd=%d, buf=%p, len=%d, dest=%s)\n", strerror(errno), udpfd, buf, l, inet_ntoa(addr.sin_addr)); STAT(tunnel_tx_errors); return; @@ -1027,23 +1028,23 @@ } if (!mss) return; // not found - orig = ntohs(*(uint16_t *) mss); + orig = ntohs(get_unaligned16(mss)); if (orig <= MSS) return; // mss OK LOG(5, s, t, "TCP: %s:%u -> %s:%u SYN%s: adjusted mss from %u to %u\n", - fmtaddr(*(in_addr_t *) (buf + 12), 0), ntohs(*(uint16_t *) tcp), - fmtaddr(*(in_addr_t *) (buf + 16), 1), ntohs(*(uint16_t *) (tcp + 2)), + fmtaddr(get_unalignedin(buf + 12), 0), ntohs(get_unaligned16(tcp)), + fmtaddr(get_unalignedin(buf + 16), 1), ntohs(get_unaligned16(tcp + 2)), (tcp[13] & TCP_FLAG_ACK) ? ",ACK" : "", orig, MSS); // set mss - *(int16_t *) mss = htons(MSS); + put_unaligned16(mss, htons(MSS)); // adjust checksum (see rfc1141) sum = orig + (~MSS & 0xffff); - sum += ntohs(*(uint16_t *) (tcp + 16)); + sum += ntohs(get_unaligned16(tcp + 16)); sum = (sum & 0xffff) + (sum >> 16); - *(uint16_t *) (tcp + 16) = htons(sum); + put_unaligned16((tcp + 16), htons(sum)); } // process outgoing (to tunnel) IP @@ -1086,7 +1087,8 @@ return; } - ip = *(uint32_t *)(buf + 16); + // FIXME convert from network byte order??? + ip = get_unaligned32(buf + 16); if (!(s = sessionbyip(ip))) { // Is this a packet for a session that doesn't exist? @@ -1101,8 +1103,9 @@ if (rate++ < config->icmp_rate) // Only send a max of icmp_rate per second. { - LOG(4, 0, 0, "IP: Sending ICMP host unreachable to %s\n", fmtaddr(*(in_addr_t *)(buf + 12), 0)); - host_unreachable(*(in_addr_t *)(buf + 12), *(uint16_t *)(buf + 4), + LOG(4, 0, 0, "IP: Sending ICMP host unreachable to %s\n", fmtaddr(get_unalignedin(buf + 12), 0)); + // FIXME convert from network byte order? + host_unreachable(get_unalignedin(buf + 12), get_unaligned16(buf + 4), config->bind_address ? config->bind_address : my_address, buf, len); } return; @@ -1154,7 +1157,7 @@ return; // adjust MSS on SYN and SYN,ACK packets with options - if ((ntohs(*(uint16_t *) (buf + 6)) & 0x1fff) == 0 && buf[9] == IPPROTO_TCP) // first tcp fragment + if ((ntohs(get_unaligned16(buf + 6)) & 0x1fff) == 0 && buf[9] == IPPROTO_TCP) // first tcp fragment { int ihl = (buf[0] & 0xf) * 4; // length of IP header if (len >= ihl + 20 && (buf[ihl + 13] & TCP_FLAG_SYN) && ((buf[ihl + 12] >> 4) > 5)) @@ -1240,12 +1243,13 @@ return; } - ip6 = *(struct in6_addr *)(buf+24); + memcpy(&ip6, (buf+24), sizeof(struct in6_addr)); s = sessionbyipv6(ip6); if (s == 0) { - ip = *(uint32_t *)(buf + 32); + // Convert from network byte order? + ip = get_unaligned32(buf + 32); s = sessionbyip(ip); } @@ -1332,7 +1336,8 @@ buf += 4; len -= 4; - ip = *(in_addr_t *)(buf + 16); + // Convert from network byte order + ip = get_unalignedin(buf + 16); if (!session[s].ip) return; @@ -1366,10 +1371,10 @@ static void control16(controlt * c, uint16_t avp, uint16_t val, uint8_t m) { uint16_t l = (m ? 0x8008 : 0x0008); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); - *(uint16_t *) (c->buf + c->length + 6) = htons(val); + put_unaligned16((c->buf + c->length + 0), htons(l)); + put_unaligned16((c->buf + c->length + 2), htons(0)); + put_unaligned16((c->buf + c->length + 4), htons(avp)); + put_unaligned16((c->buf + c->length + 6), htons(val)); c->length += 8; } @@ -1377,10 +1382,10 @@ static void control32(controlt * c, uint16_t avp, uint32_t val, uint8_t m) { uint16_t l = (m ? 0x800A : 0x000A); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); - *(uint32_t *) (c->buf + c->length + 6) = htonl(val); + put_unaligned16((c->buf + c->length + 0), htons(l)); + put_unaligned16((c->buf + c->length + 2), htons(0)); + put_unaligned16((c->buf + c->length + 4), htons(avp)); + put_unaligned16((c->buf + c->length + 6), htonl(val)); c->length += 10; } @@ -1388,9 +1393,9 @@ static void controls(controlt * c, uint16_t avp, char *val, uint8_t m) { uint16_t l = ((m ? 0x8000 : 0) + strlen(val) + 6); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); + put_unaligned16((c->buf + c->length + 0), htons(l)); + put_unaligned16((c->buf + c->length + 2), htons(0)); + put_unaligned16((c->buf + c->length + 4), htons(avp)); memcpy(c->buf + c->length + 6, val, strlen(val)); c->length += 6 + strlen(val); } @@ -1399,9 +1404,9 @@ static void controlb(controlt * c, uint16_t avp, uint8_t *val, unsigned int len, uint8_t m) { uint16_t l = ((m ? 0x8000 : 0) + len + 6); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); + put_unaligned16((c->buf + c->length + 0), htons(l)); + put_unaligned16((c->buf + c->length + 2), htons(0)); + put_unaligned16((c->buf + c->length + 4), htons(avp)); memcpy(c->buf + c->length + 6, val, len); c->length += 6 + len; } @@ -1419,7 +1424,7 @@ } assert(c); c->next = 0; - *(uint16_t *) (c->buf + 0) = htons(0xC802); // flags/ver + put_unaligned16((c->buf + 0), htons(0xC802)); // flags/ver c->length = 12; control16(c, 0, mtype, 1); return c; @@ -1433,22 +1438,22 @@ if (tunnel[t].controlc) // Messages queued; They will carry the ack. return; - *(uint16_t *) (buf + 0) = htons(0xC802); // flags/ver - *(uint16_t *) (buf + 2) = htons(12); // length - *(uint16_t *) (buf + 4) = htons(tunnel[t].far); // tunnel - *(uint16_t *) (buf + 6) = htons(0); // session - *(uint16_t *) (buf + 8) = htons(tunnel[t].ns); // sequence - *(uint16_t *) (buf + 10) = htons(tunnel[t].nr); // sequence + put_unaligned16((buf + 0), htons(0xC802)); // flags/ver + put_unaligned16((buf + 2), htons(12)); // length + put_unaligned16((buf + 4), htons(tunnel[t].far)); // tunnel + put_unaligned16((buf + 6), htons(0)); // session + put_unaligned16((buf + 8), htons(tunnel[t].ns)); // sequence + put_unaligned16((buf + 10), htons(tunnel[t].nr)); // sequence tunnelsend(buf, 12, t); } // add a control message to a tunnel, and send if within window static void controladd(controlt *c, sessionidt far, tunnelidt t) { - *(uint16_t *) (c->buf + 2) = htons(c->length); // length - *(uint16_t *) (c->buf + 4) = htons(tunnel[t].far); // tunnel - *(uint16_t *) (c->buf + 6) = htons(far); // session - *(uint16_t *) (c->buf + 8) = htons(tunnel[t].ns); // sequence + put_unaligned16((c->buf + 2), htons(c->length)); // length + put_unaligned16((c->buf + 4), htons(tunnel[t].far)); // tunnel + put_unaligned16((c->buf + 6), htons(far)); // session + put_unaligned16((c->buf + 8), htons(tunnel[t].ns)); // sequence tunnel[t].ns++; // advance sequence // link in message in to queue if (tunnel[t].controlc) @@ -1627,8 +1632,8 @@ if (error) { uint8_t buf[4]; - *(uint16_t *) buf = htons(result); - *(uint16_t *) (buf+2) = htons(error); + put_unaligned16(buf , htons(result)); + put_unaligned16((buf+2), htons(error)); controlb(c, 1, buf, 4, 1); } else @@ -1674,12 +1679,12 @@ *q = ConfigReq; q[1] = session[s].unique_id & 0xf; // ID, dont care, we only send one type of request - *(uint16_t *) (q + 2) = htons(10); // packet length + put_unaligned16((q + 2), htons(10)); // packet length q[4] = 3; // ip address option q[5] = 6; // option length - *(in_addr_t *) (q + 6) = config->peer_address ? config->peer_address : + put_unalignedin((q + 6), config->peer_address ? config->peer_address : config->bind_address ? config->bind_address : - my_address; // send my IP + my_address); // send my IP tunnelsend(buf, 10 + (q - buf), t); // send it restart_timer(s, ipcp); @@ -1700,11 +1705,11 @@ q[1] = session[s].unique_id & 0xf; // ID, don't care, we // only send one type // of request - *(uint16_t *) (q + 2) = htons(14); + put_unaligned16((q + 2), htons(14)); q[4] = 1; // interface identifier option q[5] = 10; // option length - *(uint32_t *) (q + 6) = 0; // We'll be prefix::1 - *(uint32_t *) (q + 10) = 0; + put_unaligned32((q + 6), 0); // We'll be prefix::1 + put_unaligned32((q + 10), 0); q[13] = 1; tunnelsend(buf, 14 + (q - buf), t); // send it @@ -1816,8 +1821,8 @@ { uint8_t buf[64]; int l = 4; - *(uint16_t *) buf = htons(result); - *(uint16_t *) (buf+2) = htons(error); + put_unaligned16(buf , htons(result)); + put_unaligned16((buf+2), htons(error)); if (msg) { int m = strlen(msg); @@ -1867,12 +1872,12 @@ } if (*buf & 0x40) { // length - l = ntohs(*(uint16_t *) p); + l = ntohs(get_unaligned16(p)); p += 2; } - t = ntohs(*(uint16_t *) p); + t = ntohs(get_unaligned16(p)); p += 2; - s = ntohs(*(uint16_t *) p); + s = ntohs(get_unaligned16(p)); p += 2; if (s >= MAXSESSION) { @@ -1888,14 +1893,14 @@ } if (*buf & 0x08) { // ns/nr - ns = ntohs(*(uint16_t *) p); + ns = ntohs(get_unaligned16(p)); p += 2; - nr = ntohs(*(uint16_t *) p); + nr = ntohs(get_unaligned16(p)); p += 2; } if (*buf & 0x02) { // offset - uint16_t o = ntohs(*(uint16_t *) p); + uint16_t o = ntohs(get_unaligned16(p)); p += o + 2; } if ((p - buf) > l) @@ -2045,7 +2050,7 @@ // process AVPs while (l && !(fatal & 0x80)) // 0x80 = mandatory AVP { - uint16_t n = (ntohs(*(uint16_t *) p) & 0x3FF); + uint16_t n = (ntohs(get_unaligned16(p)) & 0x3FF); uint8_t *b = p; uint8_t flags = *p; uint16_t mtype; @@ -2067,9 +2072,9 @@ continue; // next } b += 2; - if (*(uint16_t *) (b)) + if (get_unaligned16(b)) { - LOG(2, s, t, "Unknown AVP vendor %d\n", ntohs(*(uint16_t *) (b))); + LOG(2, s, t, "Unknown AVP vendor %d\n", ntohs(get_unaligned16(b))); fatal = flags; result = 2; // general error error = 6; // generic vendor-specific error @@ -2077,7 +2082,7 @@ continue; // next } b += 2; - mtype = ntohs(*(uint16_t *) (b)); + mtype = ntohs(get_unaligned16(b)); b += 2; n -= 6; @@ -2117,7 +2122,7 @@ // Unhide the AVP unhide_value(b, n, mtype, session[s].random_vector, session[s].random_vector_length); - orig_len = ntohs(*(uint16_t *) b); + orig_len = ntohs(get_unaligned16(b)); if (orig_len > n + 2) { LOG(1, s, t, "Original length %d too long in hidden AVP of length %d; wrong secret?\n", @@ -2140,13 +2145,13 @@ switch (mtype) { case 0: // message type - message = ntohs(*(uint16_t *) b); + message = ntohs(get_unaligned16(b)); mandatory = flags & 0x80; LOG(4, s, t, " Message type = %d (%s)\n", *b, l2tp_code(message)); break; case 1: // result code { - uint16_t rescode = ntohs(*(uint16_t *) b); + uint16_t rescode = ntohs(get_unaligned16(b)); const char* resdesc = "(unknown)"; if (message == 4) { /* StopCCN */ @@ -2160,7 +2165,7 @@ LOG(4, s, t, " Result Code %d: %s\n", rescode, resdesc); if (n >= 4) { - uint16_t errcode = ntohs(*(uint16_t *)(b + 2)); + uint16_t errcode = ntohs(get_unaligned16(b + 2)); LOG(4, s, t, " Error Code %d: %s\n", errcode, l2tp_error_code(errcode)); } if (n > 4) @@ -2171,7 +2176,7 @@ break; case 2: // protocol version { - version = ntohs(*(uint16_t *) (b)); + version = ntohs(get_unaligned16(b)); LOG(4, s, t, " Protocol version = %d\n", version); if (version && version != 0x0100) { // allow 0.0 and 1.0 @@ -2209,11 +2214,11 @@ LOG(4, s, t, " Vendor name = \"%s\"\n", tunnel[t].vendor); break; case 9: // assigned tunnel - tunnel[t].far = ntohs(*(uint16_t *) (b)); + tunnel[t].far = ntohs(get_unaligned16(b)); LOG(4, s, t, " Remote tunnel id = %d\n", tunnel[t].far); break; case 10: // rx window - tunnel[t].window = ntohs(*(uint16_t *) (b)); + tunnel[t].window = ntohs(get_unaligned16(b)); if (!tunnel[t].window) tunnel[t].window = 1; // window of 0 is silly LOG(4, s, t, " rx window = %d\n", tunnel[t].window); @@ -2230,18 +2235,18 @@ break; case 14: // assigned session - asession = session[s].far = ntohs(*(uint16_t *) (b)); + asession = session[s].far = ntohs(get_unaligned16(b)); LOG(4, s, t, " assigned session = %d\n", asession); break; case 15: // call serial number - LOG(4, s, t, " call serial number = %d\n", ntohl(*(uint32_t *)b)); + LOG(4, s, t, " call serial number = %d\n", ntohl(get_unaligned32(b))); break; case 18: // bearer type - LOG(4, s, t, " bearer type = %d\n", ntohl(*(uint32_t *)b)); + LOG(4, s, t, " bearer type = %d\n", ntohl(get_unaligned32(b))); // TBA - for RADIUS break; case 19: // framing type - LOG(4, s, t, " framing type = %d\n", ntohl(*(uint32_t *)b)); + LOG(4, s, t, " framing type = %d\n", ntohl(get_unaligned32(b))); // TBA break; case 21: // called number @@ -2259,7 +2264,7 @@ case 24: // tx connect speed if (n == 4) { - session[s].tx_connect_speed = ntohl(*(uint32_t *)b); + session[s].tx_connect_speed = ntohl(get_unaligned32(b)); } else { @@ -2274,7 +2279,7 @@ case 38: // rx connect speed if (n == 4) { - session[s].rx_connect_speed = ntohl(*(uint32_t *)b); + session[s].rx_connect_speed = ntohl(get_unaligned32(b)); } else { @@ -2288,13 +2293,13 @@ break; case 25: // Physical Channel ID { - uint32_t tmp = ntohl(*(uint32_t *) b); + uint32_t tmp = ntohl(get_unaligned32(b)); LOG(4, s, t, " Physical Channel ID <%X>\n", tmp); break; } case 29: // Proxy Authentication Type { - uint16_t atype = ntohs(*(uint16_t *)b); + uint16_t atype = ntohs(get_unaligned16(b)); LOG(4, s, t, " Proxy Auth Type %d (%s)\n", atype, ppp_auth_type(atype)); break; } @@ -2314,7 +2319,7 @@ } case 32: // Proxy Authentication ID { - uint16_t authid = ntohs(*(uint16_t *)(b)); + uint16_t authid = ntohs(get_unaligned16(b)); LOG(4, s, t, " Proxy Auth ID (%d)\n", authid); break; } @@ -2327,7 +2332,7 @@ while (p + 1 < e && p[1] && p + p[1] <= e) { if (*p == 5 && p[1] == 6) // Magic-Number - amagic = ntohl(*(uint32_t *) (p + 2)); + amagic = ntohl(get_unaligned32(p + 2)); else if (*p == 7) // Protocol-Field-Compression aflags |= SESSION_PFC; else if (*p == 8) // Address-and-Control-Field-Compression @@ -2515,7 +2520,7 @@ } else { - proto = ntohs(*(uint16_t *) p); + proto = ntohs(get_unaligned16(p)); p += 2; l -= 2; } @@ -2620,8 +2625,8 @@ *q = ProtocolRej; *(q + 1) = ++sess_local[s].lcp_ident; - *(uint16_t *)(q + 2) = htons(l); - *(uint16_t *)(q + 4) = htons(proto); + put_unaligned16((q + 2), htons(l)); + put_unaligned16((q + 4), htons(proto)); memcpy(q + 6, p, l - 6); if (proto == PPPIPV6CP) @@ -2657,9 +2662,9 @@ return; } - if (*(uint16_t *) (buf + 2) == htons(PKTIP)) // IPv4 + if (get_unaligned16(buf + 2) == htons(PKTIP)) // IPv4 processipout(buf, len); - else if (*(uint16_t *) (buf + 2) == htons(PKTIPV6) // IPV6 + else if (get_unaligned16(buf + 2) == htons(PKTIPV6) // IPV6 && config->ipv6_prefix.s6_addr[0]) processipv6out(buf, len); @@ -2933,8 +2938,8 @@ *q = EchoReq; *(uint8_t *)(q + 1) = (time_now % 255); // ID - *(uint16_t *)(q + 2) = htons(8); // Length - *(uint32_t *)(q + 4) = 0; // Magic Number (not supported) + put_unaligned16(q + 2, htons(8)); // Length + put_unaligned32(q + 4, 0); // Magic Number (not supported) LOG(4, s, session[s].tunnel, "No data in %d seconds, sending LCP ECHO\n", (int)(time_now - session[s].last_packet)); @@ -4589,10 +4594,14 @@ // This session just got dropped on us by the master or something. // Make sure our tables up up to date... // -int load_session(sessionidt s, sessiont *new) +int load_session(sessionidt s, uint8_t *newp) { int i; int newip = 0; + sessiont mynew; + sessiont *new = &mynew; + + memcpy(&mynew, newp, sizeof(mynew)); // Sanity checks. if (new->ip_pool_index >= MAXIPPOOL || @@ -5313,10 +5322,10 @@ if ((*buf >> 4) != 4) // IPv4 return 0; - frag_offset = ntohs(*(uint16_t *) (buf + 6)) & 0x1fff; + frag_offset = ntohs(get_unaligned16(buf + 6)) & 0x1fff; proto = buf[9]; - src_ip = *(in_addr_t *) (buf + 12); - dst_ip = *(in_addr_t *) (buf + 16); + src_ip = get_unalignedin(buf + 12); + dst_ip = get_unalignedin(buf + 16); if (frag_offset == 0 && (proto == IPPROTO_TCP || proto == IPPROTO_UDP)) { @@ -5324,8 +5333,8 @@ if (len < l + 4) // ports return 0; - src_port = ntohs(*(uint16_t *) (buf + l)); - dst_port = ntohs(*(uint16_t *) (buf + l + 2)); + src_port = ntohs(get_unaligned16(buf + l)); + dst_port = ntohs(get_unaligned16(buf + l + 2)); if (proto == IPPROTO_TCP) { if (len < l + 14) // flags diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/l2tpns.h l2tpns-2.1.10/l2tpns.h --- l2tpns-2.1.10.orig/l2tpns-2.1.10/l2tpns.h 2005-11-04 14:41:50.000000000 +0000 +++ l2tpns-2.1.10/l2tpns.h 2005-11-26 23:20:10.000000000 +0000 @@ -745,7 +745,7 @@ int run_plugins(int plugin_type, void *data); void rebuild_address_pool(void); void throttle_session(sessionidt s, int rate_in, int rate_out); -int load_session(sessionidt, sessiont *); +int load_session(sessionidt, uint8_t *); void become_master(void); // We're the master; kick off any required master initializations. diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/Makefile l2tpns-2.1.10/Makefile --- l2tpns-2.1.10.orig/l2tpns-2.1.10/Makefile 2005-08-12 11:31:22.000000000 +0100 +++ l2tpns-2.1.10/Makefile 2005-11-30 23:38:12.000000000 +0000 @@ -18,7 +18,7 @@ LD = gcc INCLUDES = -I. CPPFLAGS = $(INCLUDES) $(DEFINES) -CFLAGS = -Wall -Wformat-security -Wno-format-zero-length $(OPTIM) +CFLAGS = -Wall -Wcast-align -Wformat-security -Wno-format-zero-length $(OPTIM) LDFLAGS = LDLIBS = INSTALL = install -c -D -o root -g root @@ -110,21 +110,23 @@ ## Dependencies: (autogenerated) ## arp.o: arp.c l2tpns.h cli.o: cli.c l2tpns.h constants.h util.h cluster.h tbf.h ll.h bgp.h -cluster.o: cluster.c l2tpns.h cluster.h util.h tbf.h bgp.h +cluster.o: cluster.c l2tpns.h cluster.h util.h tbf.h unaligned.h bgp.h constants.o: constants.c constants.h control.o: control.c l2tpns.h control.h -icmp.o: icmp.c l2tpns.h +icmp.o: icmp.c l2tpns.h unaligned.h l2tpns.o: l2tpns.c md5.h l2tpns.h cluster.h plugin.h ll.h constants.h \ - control.h util.h tbf.h bgp.h + control.h util.h tbf.h unaligned.h bgp.h ll.o: ll.c ll.h md5.o: md5.c md5.h -ppp.o: ppp.c l2tpns.h constants.h plugin.h util.h tbf.h cluster.h -radius.o: radius.c constants.h l2tpns.h plugin.h util.h cluster.h +ppp.o: ppp.c l2tpns.h constants.h plugin.h util.h tbf.h cluster.h \ + unaligned.h +radius.o: radius.c md5.h constants.h l2tpns.h plugin.h util.h cluster.h \ + unaligned.h tbf.o: tbf.c l2tpns.h util.h tbf.h util.o: util.c l2tpns.h bgp.h bgp.o: bgp.c l2tpns.h bgp.h util.h -autosnoop.so: autosnoop.c l2tpns.h plugin.h -autothrottle.so: autothrottle.c l2tpns.h plugin.h +autosnoop.so: autosnoop.c l2tpns.h plugin.h unaligned.h +autothrottle.so: autothrottle.c l2tpns.h plugin.h unaligned.h garden.so: garden.c l2tpns.h plugin.h control.h sessionctl.so: sessionctl.c l2tpns.h plugin.h control.h setrxspeed.so: setrxspeed.c l2tpns.h plugin.h diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/ppp.c l2tpns-2.1.10/ppp.c --- l2tpns-2.1.10.orig/l2tpns-2.1.10/ppp.c 2005-11-04 14:41:50.000000000 +0000 +++ l2tpns-2.1.10/ppp.c 2005-12-01 00:09:35.000000000 +0000 @@ -13,6 +13,7 @@ #include "util.h" #include "tbf.h" #include "cluster.h" +#include "unaligned.h" extern tunnelt *tunnel; extern sessiont *session; @@ -44,7 +45,7 @@ return; } - if ((hl = ntohs(*(uint16_t *) (p + 2))) > l) + if ((hl = ntohs(get_unaligned16(p + 2))) > l) { LOG(1, s, t, "Length mismatch PAP %u/%u\n", hl, l); STAT(tunnel_rx_errors); @@ -98,7 +99,7 @@ else *p = 3; // cant authorise p[1] = id; - *(uint16_t *) (p + 2) = htons(5); // length + put_unaligned16((p + 2), htons(5)); // length p[4] = 0; // no message tunnelsend(b, 5 + (p - b), t); // send it @@ -156,7 +157,7 @@ return; } - if ((hl = ntohs(*(uint16_t *) (p + 2))) > l) + if ((hl = ntohs(get_unaligned16(p + 2))) > l) { LOG(1, s, t, "Length mismatch CHAP %u/%u\n", hl, l); STAT(tunnel_rx_errors); @@ -252,7 +253,7 @@ uint8_t *o = (p + 4); LOG_HEX(5, "PPP LCP Packet", p, l); - LOG(4, 0, 0, "PPP LCP Packet type %d (%s len %d)\n", *p, ppp_code((int)*p), ntohs( ((uint16_t *) p)[1]) ); + LOG(4, 0, 0, "PPP LCP Packet type %d (%s len %d)\n", *p, ppp_code((int)*p), ntohs( get_unaligned16(p+2) )); LOG(4, 0, 0, "Length: %d\n", l); if (*p != ConfigReq && *p != ConfigRej && *p != ConfigAck) return; @@ -277,14 +278,14 @@ { case 1: // Maximum-Receive-Unit if (length == 4) - LOG(4, 0, 0, " %s %d\n", ppp_lcp_option(type), ntohs(*(uint16_t *)(o + 2))); + LOG(4, 0, 0, " %s %d\n", ppp_lcp_option(type), ntohs(get_unaligned16(o + 2))); else LOG(4, 0, 0, " %s odd length %d\n", ppp_lcp_option(type), length); break; case 2: // Async-Control-Character-Map if (length == 6) { - uint32_t asyncmap = ntohl(*(uint32_t *)(o + 2)); + uint32_t asyncmap = ntohl(get_unaligned32(o + 2)); LOG(4, 0, 0, " %s %x\n", ppp_lcp_option(type), asyncmap); } else @@ -293,13 +294,13 @@ case 3: // Authentication-Protocol if (length == 4) { - int proto = ntohs(*(uint16_t *)(o + 2)); + int proto = ntohs(get_unaligned16(o + 2)); LOG(4, 0, 0, " %s 0x%x (%s)\n", ppp_lcp_option(type), proto, proto == PPPPAP ? "PAP" : "UNSUPPORTED"); } else if (length == 5) { - int proto = ntohs(*(uint16_t *)(o + 2)); + int proto = ntohs(get_unaligned16(o + 2)); int algo = *(o + 4); LOG(4, 0, 0, " %s 0x%x 0x%x (%s)\n", ppp_lcp_option(type), proto, algo, (proto == PPPCHAP && algo == 5) ? "CHAP MD5" : "UNSUPPORTED"); @@ -309,14 +310,14 @@ break; case 4: // Quality-Protocol { - uint32_t qp = ntohl(*(uint32_t *)(o + 2)); + uint32_t qp = ntohl(get_unaligned32(o + 2)); LOG(4, 0, 0, " %s %x\n", ppp_lcp_option(type), qp); } break; case 5: // Magic-Number if (length == 6) { - uint32_t magicno = ntohl(*(uint32_t *)(o + 2)); + uint32_t magicno = ntohl(get_unaligned32(o + 2)); LOG(4, 0, 0, " %s %x\n", ppp_lcp_option(type), magicno); } else @@ -459,7 +460,7 @@ *q = CodeRej; *(q + 1) = ++sess_local[s].lcp_ident; - *(uint16_t *)(q + 2) = htons(l); + put_unaligned16((q + 2), htons(l)); memcpy(q + 4, p, l - 4); LOG(2, s, t, "Unexpected %s code %s\n", pname, ppp_code(*p)); @@ -487,7 +488,7 @@ return ; } - if ((hl = ntohs(*(uint16_t *) (p + 2))) > l) + if ((hl = ntohs(get_unaligned16(p + 2))) > l) { LOG(1, s, t, "Length mismatch LCP %u/%u\n", hl, l); STAT(tunnel_rx_errors); @@ -517,7 +518,7 @@ { case 3: // Authentication-Protocol { - int proto = ntohs(*(uint16_t *)(o + 2)); + int proto = ntohs(get_unaligned16(o + 2)); if (proto == PPPPAP) authtype = AUTHPAP; else if (proto == PPPCHAP && *(o + 4) == 5) @@ -575,11 +576,11 @@ switch (type) { case 1: // Maximum-Receive-Unit - session[s].mru = ntohs(*(uint16_t *)(o + 2)); + session[s].mru = ntohs(get_unaligned16(o + 2)); break; case 2: // Async-Control-Character-Map - if (!ntohl(*(uint32_t *)(o + 2))) // all bits zero is OK + if (!ntohl(get_unaligned32(o + 2))) // all bits zero is OK break; LOG(3, s, t, " Remote requesting asyncmap. Rejecting.\n"); @@ -588,7 +589,7 @@ case 3: // Authentication-Protocol { - int proto = ntohs(*(uint16_t *)(o + 2)); + int proto = ntohs(get_unaligned16(o + 2)); char proto_name[] = "0x0000"; int alen; @@ -636,7 +637,7 @@ break; case 5: // Magic-Number - magicno = ntohl(*(uint32_t *)(o + 2)); + magicno = ntohl(get_unaligned32(o + 2)); break; case 4: // Quality-Protocol @@ -655,7 +656,7 @@ if (response) { l = q - response; // LCP packet length - *((uint16_t *) (response + 2)) = htons(l); // update header + put_unaligned16((response + 2), htons(l)); // update header } else { @@ -671,7 +672,7 @@ response = makeppp(b, sizeof(b), p, 2, s, t, PPPLCP); if (!response) return; *response = TerminateAck; - *((uint16_t *) (response + 2)) = htons(l = 4); + put_unaligned16((response + 2), htons(l = 4)); break; case Stopped: @@ -736,7 +737,7 @@ case 1: // Maximum-Receive-Unit if (*p == ConfigNak) { - sess_local[s].ppp_mru = ntohs(*(uint16_t *)(o + 2)); + sess_local[s].ppp_mru = ntohs(get_unaligned16(o + 2)); LOG(3, s, t, " Remote requested MRU of %u\n", sess_local[s].ppp_mru); } else @@ -753,7 +754,7 @@ if (*p == ConfigNak) { - int proto = ntohs(*(uint16_t *)(o + 2)); + int proto = ntohs(get_unaligned16(o + 2)); if (proto == PPPPAP) { authtype = config->radius_authtypes & AUTHPAP; @@ -805,7 +806,7 @@ uint8_t *response = makeppp(b, sizeof(b), p, 2, s, t, PPPLCP); if (!response) return; *response = TerminateAck; - *((uint16_t *) (response + 2)) = htons(l = 4); + put_unaligned16((response + 2), htons(l = 4)); LOG(3, s, t, "LCP: send %s\n", ppp_code(*response)); if (config->debug > 3) dumplcp(response, l); @@ -878,7 +879,7 @@ else if (*p == EchoReq) { *p = EchoReply; // reply - *(uint32_t *) (p + 4) = htonl(session[s].magic); // our magic number + put_unaligned32((p + 4), htonl(session[s].magic)); // our magic number q = makeppp(b, sizeof(b), p, l, s, t, PPPLCP); if (!q) return; @@ -941,7 +942,7 @@ return ; } - if ((hl = ntohs(*(uint16_t *) (p + 2))) > l) + if ((hl = ntohs(get_unaligned16(p + 2))) > l) { LOG(1, s, t, "Length mismatch IPCP %u/%u\n", hl, l); STAT(tunnel_rx_errors); @@ -1048,7 +1049,7 @@ if (response) { l = q - response; // IPCP packet length - *((uint16_t *) (response + 2)) = htons(l); // update header + put_unaligned16((response + 2), htons(l)); // update header } else if (gotip) { @@ -1070,7 +1071,7 @@ response = makeppp(b, sizeof(b), p, 2, s, t, PPPIPCP); if (!response) return; *response = TerminateAck; - *((uint16_t *) (response + 2)) = htons(l = 4); + put_unaligned16((response + 2), htons(l = 4)); break; case Stopped: @@ -1160,7 +1161,7 @@ return ; } - if ((hl = ntohs(*(uint16_t *) (p + 2))) > l) + if ((hl = ntohs(get_unaligned16(p + 2))) > l) { LOG(1, s, t, "Length mismatch IPV6CP %u/%u\n", hl, l); STAT(tunnel_rx_errors); @@ -1222,8 +1223,8 @@ gotip++; // seen address if (o[1] != 10 || o[1] > length) return; - *(uint32_t *) ident = htonl(session[s].ip); - *(uint32_t *) (ident + 4) = 0; + put_unaligned32(ident, htonl(session[s].ip)); + put_unaligned32((ident + 4), 0); if (memcmp(o + 2, ident, sizeof(ident))) { @@ -1246,7 +1247,7 @@ if (response) { l = q - response; // IPV6CP packet length - *((uint16_t *) (response + 2)) = htons(l); // update header + put_unaligned16((response + 2), htons(l)); // update header } else if (gotip) { @@ -1268,7 +1269,7 @@ response = makeppp(b, sizeof(b), p, 2, s, t, PPPIPV6CP); if (!response) return; *response = TerminateAck; - *((uint16_t *) (response + 2)) = htons(l = 4); + put_unaligned16((response + 2), htons(l = 4)); break; case Stopped: @@ -1348,7 +1349,7 @@ return ; } - ip = ntohl(*(uint32_t *)(p + 12)); + ip = ntohl(get_unaligned32(p + 12)); if (l > MAXETHER) { @@ -1372,7 +1373,7 @@ return; // adjust MSS on SYN and SYN,ACK packets with options - if ((ntohs(*(uint16_t *) (p + 6)) & 0x1fff) == 0 && p[9] == IPPROTO_TCP) // first tcp fragment + if ((ntohs(get_unaligned16(p + 6)) & 0x1fff) == 0 && p[9] == IPPROTO_TCP) // first tcp fragment { int ihl = (p[0] & 0xf) * 4; // length of IP header if (l >= ihl + 20 && (p[ihl + 13] & TCP_FLAG_SYN) && ((p[ihl + 12] >> 4) > 5)) @@ -1381,7 +1382,7 @@ // Add on the tun header p -= 4; - *(uint32_t *) p = htonl(PKTIP); + put_unaligned32(p, htonl(PKTIP)); l += 4; // Are we throttled and a slave? @@ -1443,8 +1444,8 @@ LOG_HEX(5, "IPv6", p, l); - ip = *(struct in6_addr *) (p + 8); - ipv4 = ntohl(*(uint32_t *)(p + 16)); + memcpy(&ip, (p+8), sizeof(struct in6_addr)); + ipv4 = ntohl(get_unaligned32(p + 16)); if (l > MAXETHER) { @@ -1467,8 +1468,8 @@ // Check if it's a Router Solicition message. if (*(p + 6) == 58 && *(p + 7) == 255 && *(p + 24) == 0xFF && *(p + 25) == 2 && - *(uint32_t *)(p + 26) == 0 && *(uint32_t *)(p + 30) == 0 && - *(uint32_t *)(p + 34) == 0 && + get_unaligned32(p + 26) == 0 && get_unaligned32(p + 30) == 0 && + get_unaligned32(p + 34) == 0 && *(p + 38) == 0 && *(p + 39) == 2 && *(p + 40) == 133) { LOG(3, s, t, "Got IPv6 RS\n"); send_ipv6_ra(s, t, &ip); @@ -1477,7 +1478,7 @@ // Add on the tun header p -= 4; - *(uint32_t *) p = htonl(PKTIPV6); + put_unaligned32(p, htonl(PKTIPV6)); l += 4; // Are we throttled and a slave? @@ -1631,7 +1632,7 @@ q = makeppp(b, sizeof(b), p, 2, s, t, PPPCCP); if (!q) return; *q = TerminateAck; - *((uint16_t *) (q + 2)) = htons(l = 4); + put_unaligned16((q + 2), htons(l = 4)); break; case Stopped: @@ -1732,7 +1733,7 @@ q[4] = 16; // value size (size of challenge) memcpy(q + 5, radius[r].auth, 16); // challenge strcpy((char *) q + 21, hostname); // our name - *(uint16_t *) (q + 2) = htons(strlen(hostname) + 21); // length + put_unaligned16((q + 2), htons(strlen(hostname) + 21)); // length tunnelsend(b, strlen(hostname) + 21 + (q - b), t); // send it } @@ -1749,20 +1750,20 @@ return NULL; } - *(uint16_t *) (b + 0) = htons(0x0002); // L2TP with no options - *(uint16_t *) (b + 2) = htons(tunnel[t].far); // tunnel - *(uint16_t *) (b + 4) = htons(session[s].far); // session + put_unaligned16((b + 0), htons(0x0002)); // L2TP with no options + put_unaligned16((b + 2), htons(tunnel[t].far)); // tunnel + put_unaligned16((b + 4), htons(session[s].far)); // session b += 6; if (mtype == PPPLCP || !(session[s].flags & SESSION_ACFC)) { - *(uint16_t *) b = htons(0xFF03); // HDLC header + put_unaligned16(b, htons(0xFF03)); // HDLC header b += 2; } if (mtype < 0x100 && session[s].flags & SESSION_PFC) *b++ = mtype; else { - *(uint16_t *) b = htons(mtype); + put_unaligned16(b, htons(mtype)); b += 2; } @@ -1790,13 +1791,13 @@ if (authtype == AUTHCHAP) { len = *b++ = 5; // length - *(uint16_t *) b = htons(PPPCHAP); b += 2; + put_unaligned16(b, htons(PPPCHAP)); b += 2; *b++ = 5; // MD5 } else if (authtype == AUTHPAP) { len = *b++ = 4; // length - *(uint16_t *) b = htons(PPPPAP); b += 2; + put_unaligned16(b, htons(PPPPAP)); b += 2; } else { @@ -1829,17 +1830,17 @@ if (sess_local[s].ppp_mru) { *l++ = 1; *l++ = 4; // Maximum-Receive-Unit (length 4) - *(uint16_t *) l = htons(sess_local[s].ppp_mru); l += 2; + put_unaligned16(l, htons(sess_local[s].ppp_mru)); l += 2; } if (authtype) l += add_lcp_auth(l, sizeof(b) - (l - b), authtype); *l++ = 5; *l++ = 6; // Magic-Number (length 6) - *(uint32_t *) l = htonl(session[s].magic); + put_unaligned32(l, htonl(session[s].magic)); l += 4; - *(uint16_t *)(q + 2) = htons(l - q); // Length + put_unaligned16((q + 2), htons(l - q)); // Length LOG_HEX(5, "PPPLCP", q, l - q); if (config->debug > 3) dumplcp(q, l - q); @@ -1860,7 +1861,7 @@ *q = ConfigReq; *(q + 1) = ++sess_local[s].lcp_ident; // ID - *(uint16_t *)(q + 2) = htons(4); // Length + put_unaligned16((q + 2), htons(4)); // Length LOG_HEX(5, "PPPCCP", q, 4); tunnelsend(b, (q - b) + 4 , t); diff -ur l2tpns-2.1.10.orig/l2tpns-2.1.10/radius.c l2tpns-2.1.10/radius.c --- l2tpns-2.1.10.orig/l2tpns-2.1.10/radius.c 2005-10-19 04:09:30.000000000 +0100 +++ l2tpns-2.1.10/radius.c 2005-11-26 23:52:09.000000000 +0000 @@ -19,6 +19,7 @@ #include "plugin.h" #include "util.h" #include "cluster.h" +#include "unaligned.h" extern radiust *radius; extern sessiont *session; @@ -252,7 +253,7 @@ { // accounting *p = 40; // accounting type p[1] = 6; - *(uint32_t *) (p + 2) = htonl(state - RADIUSSTART + 1); // start=1, stop=2, interim=3 + put_unaligned32((p + 2), htonl(state - RADIUSSTART + 1)); // start=1, stop=2, interim=3 p += p[1]; if (s) { @@ -264,7 +265,7 @@ { // start *p = 41; // delay p[1] = 6; - *(uint32_t *) (p + 2) = htonl(time(NULL) - session[s].opened); + put_unaligned32((p + 2), htonl(time(NULL) - session[s].opened)); p += p[1]; sess_local[s].last_interim = time_now; // Setup "first" Interim } @@ -272,37 +273,37 @@ { // stop, interim *p = 42; // input octets p[1] = 6; - *(uint32_t *) (p + 2) = htonl(session[s].cin); + put_unaligned32((p + 2), htonl(session[s].cin)); p += p[1]; *p = 43; // output octets p[1] = 6; - *(uint32_t *) (p + 2) = htonl(session[s].cout); + put_unaligned32((p + 2), htonl(session[s].cout)); p += p[1]; *p = 46; // session time p[1] = 6; - *(uint32_t *) (p + 2) = htonl(time(NULL) - session[s].opened); + put_unaligned32((p + 2), htonl(time(NULL) - session[s].opened)); p += p[1]; *p = 47; // input packets p[1] = 6; - *(uint32_t *) (p + 2) = htonl(session[s].pin); + put_unaligned32((p + 2), htonl(session[s].pin)); p += p[1]; *p = 48; // output packets p[1] = 6; - *(uint32_t *) (p + 2) = htonl(session[s].pout); + put_unaligned32((p + 2), htonl(session[s].pout)); p += p[1]; *p = 52; // input gigawords p[1] = 6; - *(uint32_t *) (p + 2) = htonl(session[s].cin_wrap); + put_unaligned32((p + 2), htonl(session[s].cin_wrap)); p += p[1]; *p = 53; // output gigawords p[1] = 6; - *(uint32_t *) (p + 2) = htonl(session[s].cout_wrap); + put_unaligned32((p + 2), htonl(session[s].cout_wrap)); p += p[1]; { @@ -316,14 +317,14 @@ { *p = 5; // NAS-Port p[1] = 6; - *(uint32_t *) (p + 2) = htonl(s); + put_unaligned32((p + 2), htonl(s)); p += p[1]; } if (s && session[s].ip) { *p = 8; // Framed-IP-Address p[1] = 6; - *(uint32_t *) (p + 2) = htonl(session[s].ip); + put_unaligned32((p + 2), htonl(session[s].ip)); p += p[1]; } if (s && session[s].route[0].ip) @@ -367,11 +368,12 @@ // NAS-IP-Address *p = 4; p[1] = 6; - *(uint32_t *)(p + 2) = config->bind_address; + // FIXME does this need converting to network byte order + put_unaligned32((p + 2), config->bind_address); p += p[1]; // All AVpairs added - *(uint16_t *) (b + 2) = htons(p - b); + put_unaligned16((b + 2), htons(p - b)); if (state != RADIUSAUTH) { // Build auth for accounting packet @@ -448,7 +450,7 @@ CSTAT(processrad); LOG_HEX(5, "RADIUS Response", buf, len); - if (len < 20 || len < ntohs(*(uint16_t *) (buf + 2))) + if (len < 20 || len < ntohs(get_unaligned16(buf + 2))) { LOG(1, 0, 0, "Duff RADIUS response length %d\n", len); return ; @@ -457,7 +459,7 @@ r_code = buf[0]; // response type r_id = buf[1]; // radius reply indentifier. - len = ntohs(*(uint16_t *) (buf + 2)); + len = ntohs(get_unaligned16(buf + 2)); r = socket_index | (r_id << RADIUS_SHIFT); s = radius[r].session; LOG(3, s, session[s].tunnel, "Received %s, radius %d response for session %u (%s, id %d)\n", @@ -514,7 +516,7 @@ *p = (r_code == AccessAccept) ? 3 : 4; // ack/nak p[1] = radius[r].id; - *(uint16_t *) (p + 2) = ntohs(4); // no message + put_unaligned16((p + 2), ntohs(4)); // no message tunnelsend(b, (p - b) + 4, t); // send it LOG(3, s, session[s].tunnel, " CHAP User %s authentication %s.\n", session[s].user, @@ -529,7 +531,7 @@ // ack/nak *p = r_code; p[1] = radius[r].id; - *(uint16_t *) (p + 2) = ntohs(5); + put_unaligned16((p + 2), ntohs(5)); p[4] = 0; // no message tunnelsend(b, (p - b) + 5, t); // send it @@ -549,7 +551,7 @@ { // Framed-IP-Address if (p[1] < 6) continue; - session[s].ip = ntohl(*(uint32_t *) (p + 2)); + session[s].ip = ntohl(get_unaligned32(p + 2)); session[s].ip_pool_index = -1; LOG(3, s, session[s].tunnel, " Radius reply contains IP address %s\n", fmtaddr(htonl(session[s].ip), 0)); @@ -561,7 +563,7 @@ { // DNS address if (p[1] < 6) continue; - session[s].dns1 = ntohl(*(uint32_t *) (p + 2)); + session[s].dns1 = ntohl(get_unaligned32(p + 2)); LOG(3, s, session[s].tunnel, " Radius reply contains primary DNS address %s\n", fmtaddr(htonl(session[s].dns1), 0)); } @@ -569,7 +571,7 @@ { // DNS address if (p[1] < 6) continue; - session[s].dns2 = ntohl(*(uint32_t *) (p + 2)); + session[s].dns2 = ntohl(get_unaligned32(p + 2)); LOG(3, s, session[s].tunnel, " Radius reply contains secondary DNS address %s\n", fmtaddr(htonl(session[s].dns2), 0)); } @@ -661,7 +663,7 @@ else if (*p == 26 && p[1] >= 7) { // Vendor-Specific Attribute - int vendor = ntohl(*(int *)(p + 2)); + int vendor = ntohl(get_unaligned32(p + 2)); char attrib = *(p + 6); int attrib_length = *(p + 7) - 2; @@ -798,7 +800,7 @@ LOG(3, 0, 0, "DAE request from %s\n", fmtaddr(addr->sin_addr.s_addr, 0)); LOG_HEX(5, "DAE Request", buf, len); - if (len < 20 || len < ntohs(*(uint16_t *) (buf + 2))) + if (len < 20 || len < ntohs(get_unaligned16(buf + 2))) { LOG(1, 0, 0, "Duff DAE request length %d\n", len); return; @@ -819,7 +821,7 @@ return; } - len = ntohs(*(uint16_t *) (buf + 2)); + len = ntohs(get_unaligned16(buf + 2)); LOG(3, 0, 0, "Received DAE %s, id %d\n", radius_code(r_code), r_id); @@ -854,7 +856,8 @@ break; case 4: /* nas ip address */ - nas = *(uint32_t *) packet; // net order + // FIXME should address be converted to network byte order + nas = get_unaligned32(packet); // net order if (nas != config->bind_address) error = 403; // NAS identification mismatch @@ -862,7 +865,7 @@ break; case 5: /* nas port */ - port = ntohl(*(uint32_t *) packet); + port = ntohl(get_unaligned32(packet)); if (port < 1 || port > MAXSESSION) error = 404; @@ -871,7 +874,7 @@ case 6: /* service type */ { - uint32_t service_type = ntohl(*(uint32_t *) packet); + uint32_t service_type = ntohl(get_unaligned32(packet)); auth_only = service_type == 8; // Authenticate only LOG(4, 0, 0, " Received DAE Service-Type: %u\n", service_type); @@ -879,7 +882,8 @@ break; case 8: /* ip address */ - ip = *(uint32_t *) packet; // net order + // FIXME should this be converted from network byte order + ip = get_unaligned32(packet); // net order LOG(4, 0, 0, " Received DAE Framed-IP-Address: %s\n", fmtaddr(ip, 0)); break; @@ -910,7 +914,7 @@ case 26: /* vendor specific */ if (attribute_length >= 6 - && ntohl(*(uint32_t *) packet) == 9 // Cisco + && ntohl(get_unaligned32(packet)) == 9 // Cisco && *(packet + 4) == 1 // Cisco-AVPair && *(packet + 5) >= 2) // length { @@ -1041,11 +1045,11 @@ // add error cause *packet++ = 101; *packet++ = 6; - *(uint32_t *) packet = htonl(error); + put_unaligned32(packet, htonl(error)); len += 6; } - *((uint16_t *)(buf + 2)) = htons(len); + put_unaligned16((buf + 2), htons(len)); // make vector calc_auth(buf, len, hash, buf + 4);