diff options
Diffstat (limited to 'accel-pppd')
| -rw-r--r-- | accel-pppd/backup/backup_file.c | 8 | ||||
| -rw-r--r-- | accel-pppd/ctrl/ipoe/dhcpv4.c | 26 | ||||
| -rw-r--r-- | accel-pppd/ctrl/ipoe/dhcpv4_options.c | 14 | ||||
| -rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 50 | ||||
| -rw-r--r-- | accel-pppd/ctrl/l2tp/packet.c | 68 | ||||
| -rw-r--r-- | accel-pppd/ctrl/l2tp/packet_test.c | 2 | ||||
| -rw-r--r-- | accel-pppd/ctrl/pppoe/pppoe.c | 28 | ||||
| -rw-r--r-- | accel-pppd/ctrl/pppoe/tr101.c | 29 | ||||
| -rw-r--r-- | accel-pppd/extra/ippool.c | 4 | ||||
| -rw-r--r-- | accel-pppd/extra/ipv6pool.c | 13 | ||||
| -rw-r--r-- | accel-pppd/ifcfg.c | 4 | ||||
| -rw-r--r-- | accel-pppd/ipdb.c | 11 | ||||
| -rw-r--r-- | accel-pppd/ipv6/dhcpv6.c | 18 | ||||
| -rw-r--r-- | accel-pppd/ipv6/dhcpv6_packet.c | 111 | ||||
| -rw-r--r-- | accel-pppd/memdebug.c | 23 | ||||
| -rw-r--r-- | accel-pppd/ppp/ccp_mppe.c | 3 | ||||
| -rw-r--r-- | accel-pppd/ppp/ipv6cp_opt_intfid.c | 9 | ||||
| -rw-r--r-- | accel-pppd/ppp/ppp_ccp.c | 47 | ||||
| -rw-r--r-- | accel-pppd/ppp/ppp_ipcp.c | 47 | ||||
| -rw-r--r-- | accel-pppd/ppp/ppp_ipv6cp.c | 47 | ||||
| -rw-r--r-- | accel-pppd/ppp/ppp_lcp.c | 56 | ||||
| -rw-r--r-- | accel-pppd/radius/backup.c | 21 | ||||
| -rw-r--r-- | accel-pppd/radius/packet.c | 32 | ||||
| -rw-r--r-- | accel-pppd/session_backup.c | 11 | ||||
| -rw-r--r-- | accel-pppd/utils.h | 73 |
25 files changed, 503 insertions, 252 deletions
diff --git a/accel-pppd/backup/backup_file.c b/accel-pppd/backup/backup_file.c index 472694f0..eaaf87d2 100644 --- a/accel-pppd/backup/backup_file.c +++ b/accel-pppd/backup/backup_file.c @@ -96,7 +96,7 @@ static int fs_commit(struct backup_data *d) ptr = (uint8_t *)(tag + 1); *ptr = tag->id; ptr++; *ptr = tag->internal ? 1 : 0; ptr++; - *(uint16_t *)ptr = tag->size; + memcpy(ptr, &tag->size, sizeof(tag->size)); MD5_Update(&md5, tag + 1, 4 + tag->size); iov[i].iov_base = tag + 1; iov[i].iov_len = 4 + tag->size; @@ -278,14 +278,16 @@ static void restore_session(const char *fn, int internal) } if (!internal && ptr[1]) { - ptr += 4 + *(uint16_t *)(ptr + 2); + uint16_t tag_size; + memcpy(&tag_size, ptr + 2, sizeof(tag_size)); + ptr += 4 + tag_size; continue; } tag = fs_alloc_tag(d, 0); tag->id = *ptr; ptr++; tag->internal = (*ptr & 0x01) ? 1 : 0; ptr ++; - tag->size = *(uint16_t *)ptr; ptr += 2; + memcpy(&tag->size, ptr, sizeof(tag->size)); ptr += 2; tag->data = ptr; ptr += tag->size; list_add_tail(&tag->entry, &mod->tag_list); diff --git a/accel-pppd/ctrl/ipoe/dhcpv4.c b/accel-pppd/ctrl/ipoe/dhcpv4.c index d80a80f3..f1427e17 100644 --- a/accel-pppd/ctrl/ipoe/dhcpv4.c +++ b/accel-pppd/ctrl/ipoe/dhcpv4.c @@ -349,6 +349,12 @@ static int dhcpv4_parse_packet(struct dhcpv4_packet *pack, int len) list_add_tail(&opt->entry, &pack->options); + } + + if (dhcpv4_check_options(pack)) + return -1; + + list_for_each_entry(opt, &pack->options, entry) { if (opt->type == 53) pack->msg_type = opt->data[0]; else if (opt->type == 82) @@ -356,17 +362,14 @@ static int dhcpv4_parse_packet(struct dhcpv4_packet *pack, int len) else if (opt->type == 62) pack->client_id = opt; else if (opt->type == 50) - memcpy(&pack->request_ip, opt->data, 4); + memcpy(&pack->request_ip, opt->data, sizeof(pack->request_ip)); else if (opt->type == 54) - memcpy(&pack->server_id, opt->data, 4); + memcpy(&pack->server_id, opt->data, sizeof(pack->server_id)); } if (pack->msg_type == 0 || pack->msg_type > 8) return -1; - if (dhcpv4_check_options(pack)) - return -1; - pack->ptr = ptr; /*if (conf_verbose) { @@ -933,6 +936,7 @@ void dhcpv4_send_notify(struct dhcpv4_serv *serv, struct dhcpv4_packet *req, uns { struct dhcpv4_packet *pack = dhcpv4_packet_alloc(); uint8_t opt[8 + ETH_ALEN]; + uint32_t value; if (!pack) { log_emerg("out of memory\n"); @@ -946,8 +950,10 @@ void dhcpv4_send_notify(struct dhcpv4_serv *serv, struct dhcpv4_packet *req, uns pack->hdr->siaddr = 0; pack->hdr->giaddr = 0; - *(uint32_t *)opt = htonl(ACCEL_PPP_MAGIC); - *(uint32_t *)(opt + 4) = htonl(weight); + value = htonl(ACCEL_PPP_MAGIC); + memcpy(opt, &value, sizeof(value)); + value = htonl(weight); + memcpy(opt + sizeof(value), &value, sizeof(value)); memcpy(opt + 8, serv->hwaddr, ETH_ALEN); dhcpv4_packet_add_opt_u8(pack, 53, DHCPDISCOVER); @@ -1100,8 +1106,8 @@ int dhcpv4_relay_send(struct dhcpv4_relay *relay, struct dhcpv4_packet *request, if (server_id) { opt = dhcpv4_packet_find_opt(request, 54); if (opt) { - _server_id = *(uint32_t *)opt->data; - *(uint32_t *)opt->data = server_id; + memcpy(&_server_id, opt->data, sizeof(_server_id)); + memcpy(opt->data, &server_id, sizeof(server_id)); } } @@ -1123,7 +1129,7 @@ int dhcpv4_relay_send(struct dhcpv4_relay *relay, struct dhcpv4_packet *request, request->hdr->giaddr = giaddr; if (opt) - *(uint32_t *)opt->data = _server_id; + memcpy(opt->data, &_server_id, sizeof(_server_id)); if (n != len) return -1; diff --git a/accel-pppd/ctrl/ipoe/dhcpv4_options.c b/accel-pppd/ctrl/ipoe/dhcpv4_options.c index 042a7406..fe6c2a5f 100644 --- a/accel-pppd/ctrl/ipoe/dhcpv4_options.c +++ b/accel-pppd/ctrl/ipoe/dhcpv4_options.c @@ -205,7 +205,10 @@ static void print_message_type(const struct dhcpv4_option *opt, int elem_size, v { const char *msg_name[] = {"", "Discover", "Offer", "Request", "Decline", "Ack", "Nak", "Release", "Inform"}; - print("%s", msg_name[opt->data[0]]); + if (opt->data[0] < sizeof(msg_name) / sizeof(msg_name[0])) + print("%s", msg_name[opt->data[0]]); + else + print("%u", opt->data[0]); } static void print_request_list(const struct dhcpv4_option *opt, int elem_size, void (*print)(const char *fmt, ...)) @@ -232,14 +235,19 @@ static void print_relay_agent(const struct dhcpv4_option *opt, int elem_size, vo int type, len; while (ptr < endptr) { + if (endptr - ptr < 2) { + print("invalid"); + return; + } + if (ptr != opt->data) print(" "); type = *ptr++; len = *ptr++; - /*if (ptr + len > endptr) { + if (endptr - ptr < len) { print(" invalid"); return; - }*/ + } if (type == 1) print("{Agent-Circuit-ID "); else if (type == 2) diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index 1e3f7054..e7b1320f 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -1835,6 +1835,7 @@ static int check_notify(struct ipoe_serv *serv, struct dhcpv4_packet *pack) struct dhcpv4_option *opt = dhcpv4_packet_find_opt(pack, 43); struct ipoe_session *ses; unsigned int w; + uint32_t value; if (!opt) return 0; @@ -1842,10 +1843,12 @@ static int check_notify(struct ipoe_serv *serv, struct dhcpv4_packet *pack) if (opt->len != 8 + ETH_ALEN) return 0; - if (*(uint32_t *)opt->data != htonl(ACCEL_PPP_MAGIC)) + memcpy(&value, opt->data, sizeof(value)); + if (value != htonl(ACCEL_PPP_MAGIC)) return 0; - w = htonl(*(uint32_t *)(opt->data + 4)); + memcpy(&value, opt->data + sizeof(value), sizeof(value)); + w = ntohl(value); list_for_each_entry(ses, &serv->sessions, entry) { if (ses->xid == pack->hdr->xid && memcmp(pack->hdr->chaddr, ses->hwaddr, ETH_ALEN) == 0) { @@ -2029,6 +2032,7 @@ static void ipoe_ses_recv_dhcpv4_relay(struct dhcpv4_packet *pack) { struct ipoe_session *ses = container_of(triton_context_self(), typeof(*ses), ctx); struct dhcpv4_option *opt; + uint32_t value; if (ses->dhcpv4_relay_reply) dhcpv4_packet_free(ses->dhcpv4_relay_reply); @@ -2047,24 +2051,32 @@ static void ipoe_ses_recv_dhcpv4_relay(struct dhcpv4_packet *pack) } opt = dhcpv4_packet_find_opt(pack, 51); - if (opt) - ses->lease_time = ntohl(*(uint32_t *)opt->data); + if (opt) { + memcpy(&value, opt->data, sizeof(value)); + ses->lease_time = ntohl(value); + } opt = dhcpv4_packet_find_opt(pack, 58); - if (opt) - ses->renew_time = ntohl(*(uint32_t *)opt->data); + if (opt) { + memcpy(&value, opt->data, sizeof(value)); + ses->renew_time = ntohl(value); + } opt = dhcpv4_packet_find_opt(pack, 59); - if (opt) - ses->rebind_time = ntohl(*(uint32_t *)opt->data); + if (opt) { + memcpy(&value, opt->data, sizeof(value)); + ses->rebind_time = ntohl(value); + } opt = dhcpv4_packet_find_opt(pack, 1); - if (opt) - ses->mask = parse_dhcpv4_mask(ntohl(*(uint32_t *)opt->data)); + if (opt) { + memcpy(&value, opt->data, sizeof(value)); + ses->mask = parse_dhcpv4_mask(ntohl(value)); + } opt = dhcpv4_packet_find_opt(pack, 3); if (opt) - ses->router = *(uint32_t *)opt->data; + memcpy(&ses->router, opt->data, sizeof(ses->router)); if (pack->msg_type == DHCPOFFER) { if (ses->ses.state == AP_STATE_STARTING) { @@ -2409,7 +2421,7 @@ static void ev_radius_access_accept(struct ev_radius_t *ev) ses->siaddr = attr->val.ipaddr; break; case DHCP_Router_Address: - ses->router = *(in_addr_t *)attr->raw; + memcpy(&ses->router, attr->raw, sizeof(ses->router)); break; case DHCP_Subnet_Mask: ses->mask = ipaddr_to_prefix(attr->val.ipaddr); @@ -2977,32 +2989,38 @@ static void ipoe_serv_timeout(struct triton_timer_t *t) static void ipoe_ipv6_enable(struct ipoe_serv *serv) { struct ifreq ifr; + uint32_t addr; strcpy(ifr.ifr_name, serv->ifname); ifr.ifr_hwaddr.sa_family = AF_UNSPEC; ifr.ifr_hwaddr.sa_data[0] = 0x33; ifr.ifr_hwaddr.sa_data[1] = 0x33; - *(uint32_t *)(ifr.ifr_hwaddr.sa_data + 2) = htonl(0x02); + addr = htonl(0x02); + memcpy(ifr.ifr_hwaddr.sa_data + 2, &addr, sizeof(addr)); ioctl(sock_fd, SIOCADDMULTI, &ifr); - *(uint32_t *)(ifr.ifr_hwaddr.sa_data + 2) = htonl(0x010002); + addr = htonl(0x010002); + memcpy(ifr.ifr_hwaddr.sa_data + 2, &addr, sizeof(addr)); ioctl(sock_fd, SIOCADDMULTI, &ifr); } static void ipoe_ipv6_disable(struct ipoe_serv *serv) { struct ifreq ifr; + uint32_t addr; strcpy(ifr.ifr_name, serv->ifname); ifr.ifr_hwaddr.sa_family = AF_UNSPEC; ifr.ifr_hwaddr.sa_data[0] = 0x33; ifr.ifr_hwaddr.sa_data[1] = 0x33; - *(uint32_t *)(ifr.ifr_hwaddr.sa_data + 2) = htonl(0x02); + addr = htonl(0x02); + memcpy(ifr.ifr_hwaddr.sa_data + 2, &addr, sizeof(addr)); ioctl(sock_fd, SIOCDELMULTI, &ifr); - *(uint32_t *)(ifr.ifr_hwaddr.sa_data + 2) = htonl(0x010002); + addr = htonl(0x010002); + memcpy(ifr.ifr_hwaddr.sa_data + 2, &addr, sizeof(addr)); ioctl(sock_fd, SIOCDELMULTI, &ifr); } diff --git a/accel-pppd/ctrl/l2tp/packet.c b/accel-pppd/ctrl/l2tp/packet.c index 0a4113a0..f134666d 100644 --- a/accel-pppd/ctrl/l2tp/packet.c +++ b/accel-pppd/ctrl/l2tp/packet.c @@ -111,58 +111,6 @@ void l2tp_packet_free(struct l2tp_packet_t *pack) mempool_free(pack); } -/* - * AVPs are not aligned in any way inside the packet buffer: their offset - * depends on the length of every preceding AVP, which is peer chosen. - * Always go through memcpy() to read multi-byte fields out of them, both to - * stay portable on strict alignment architectures and to avoid tripping - * -fsanitize=alignment. - */ -static uint16_t unaligned_ntohs(const void *ptr) -{ - uint16_t val; - - memcpy(&val, ptr, sizeof(val)); - - return ntohs(val); -} - -static uint32_t unaligned_ntohl(const void *ptr) -{ - uint32_t val; - - memcpy(&val, ptr, sizeof(val)); - - return ntohl(val); -} - -static uint64_t unaligned_be64toh(const void *ptr) -{ - uint64_t val; - - memcpy(&val, ptr, sizeof(val)); - - return be64toh(val); -} - -static void unaligned_htons(void *ptr, uint16_t val) -{ - val = htons(val); - memcpy(ptr, &val, sizeof(val)); -} - -static void unaligned_htonl(void *ptr, uint32_t val) -{ - val = htonl(val); - memcpy(ptr, &val, sizeof(val)); -} - -static void unaligned_htobe64(void *ptr, uint64_t val) -{ - val = htobe64(val); - memcpy(ptr, &val, sizeof(val)); -} - static void memxor(uint8_t *dst, const uint8_t *src, size_t sz) { size_t indx; @@ -223,7 +171,7 @@ static int decode_avp(struct l2tp_avp_t *avp, const struct l2tp_attr_t *RV, } memxor(p1, avp->val, MD5_DIGEST_LENGTH); - orig_attr_len = unaligned_ntohs(p1); + orig_attr_len = u_read_be16(p1); if (orig_attr_len <= MD5_DIGEST_LENGTH - sizeof(uint16_t)) { /* Enough bytes decoded already, no need to decode padding */ @@ -271,7 +219,7 @@ out: trustworthy as the peer's knowledge of the shared secret. Bound it against the room actually available in the received AVP before letting it drive any read of the attribute value */ - orig_attr_len = unaligned_ntohs(avp->val); + orig_attr_len = u_read_be16(avp->val); if (orig_attr_len > attr_len - sizeof(uint16_t)) { log_warn("l2tp: incorrect hidden avp received (type %hu):" " deciphered attribute length too big (ciphered" @@ -502,17 +450,17 @@ int l2tp_recv(int fd, struct l2tp_packet_t **p, struct in_pktinfo *pkt_info, case ATTR_TYPE_INT16: if (orig_avp_len != sizeof(*avp) + 2) goto out_err_len; - attr->val.uint16 = unaligned_ntohs(orig_avp_val); + attr->val.uint16 = u_read_be16(orig_avp_val); break; case ATTR_TYPE_INT32: if (orig_avp_len != sizeof(*avp) + 4) goto out_err_len; - attr->val.uint32 = unaligned_ntohl(orig_avp_val); + attr->val.uint32 = u_read_be32(orig_avp_val); break; case ATTR_TYPE_INT64: if (orig_avp_len != sizeof(*avp) + 8) goto out_err_len; - attr->val.uint64 = unaligned_be64toh(orig_avp_val); + attr->val.uint64 = u_read_be64(orig_avp_val); break; case ATTR_TYPE_OCTETS: attr->val.octets = _malloc(attr->length); @@ -589,13 +537,13 @@ int l2tp_packet_send(int sock, struct l2tp_packet_t *pack) else switch (attr->attr->type) { case ATTR_TYPE_INT16: - unaligned_htons(avp->val, attr->val.int16); + u_write_be16(avp->val, attr->val.int16); break; case ATTR_TYPE_INT32: - unaligned_htonl(avp->val, attr->val.int32); + u_write_be32(avp->val, attr->val.int32); break; case ATTR_TYPE_INT64: - unaligned_htobe64(avp->val, attr->val.uint64); + u_write_be64(avp->val, attr->val.uint64); break; case ATTR_TYPE_STRING: case ATTR_TYPE_OCTETS: diff --git a/accel-pppd/ctrl/l2tp/packet_test.c b/accel-pppd/ctrl/l2tp/packet_test.c index 9f962407..a6c9a182 100644 --- a/accel-pppd/ctrl/l2tp/packet_test.c +++ b/accel-pppd/ctrl/l2tp/packet_test.c @@ -4,7 +4,7 @@ * Not part of the cmake build. Compile and run with: * gcc -O1 -g -Wall -fno-strict-aliasing -D_GNU_SOURCE \ * -fsanitize=address,undefined -fno-sanitize-recover=all \ - * -I accel-pppd/include -I accel-pppd/ctrl/l2tp \ + * -I accel-pppd -I accel-pppd/include -I accel-pppd/ctrl/l2tp \ * -o /tmp/l2tp_packet_test \ * accel-pppd/ctrl/l2tp/packet_test.c accel-pppd/ctrl/l2tp/packet.c \ * -lcrypto && /tmp/l2tp_packet_test diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index 0e65168d..bd92cbf8 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.c +++ b/accel-pppd/ctrl/pppoe/pppoe.c @@ -556,7 +556,12 @@ static void print_tag_octets(struct pppoe_tag *tag) static void print_tag_u16(struct pppoe_tag *tag) { - log_info2("%i", (uint16_t)ntohs(*(uint16_t *)tag->tag_data)); + if (ntohs(tag->tag_len) != sizeof(uint16_t)) { + log_info2("invalid"); + return; + } + + log_info2("%i", u_read_be16(tag->tag_data)); } static void print_packet(const char *ifname, const char *op, uint8_t *pack) @@ -633,7 +638,7 @@ static void print_packet(const char *ifname, const char *op, uint8_t *pack) if (ntohs(tag->tag_len) < 4) log_info2(" <Vendor-Specific invalid>"); else - log_info2(" <Vendor-Specific %x>", ntohl(*(uint32_t *)tag->tag_data)); + log_info2(" <Vendor-Specific %x>", u_read_be32(tag->tag_data)); break; case TAG_RELAY_SESSION_ID: log_info2(" <Relay-Session-Id "); @@ -701,7 +706,10 @@ static void generate_cookie(struct pppoe_serv_t *serv, const uint8_t *src, uint8 } else memset(u1.raw + 16, 0, 4); - *(uint32_t *)(u1.raw + 20) = ts.tv_sec + conf_cookie_timeout; + { + uint32_t expires = ts.tv_sec + conf_cookie_timeout; + memcpy(u1.raw + 20, &expires, sizeof(expires)); + } for (i = 0; i < 3; i++) DES_ecb_encrypt(&u1.b[i], &u2.b[i], &ks, DES_ENCRYPT); @@ -739,8 +747,12 @@ static int check_cookie(struct pppoe_serv_t *serv, const uint8_t *src, const uin for (i = 0; i < 3; i++) DES_ecb_encrypt(&u2.b[i], &u1.b[i], &ks, DES_DECRYPT); - if (*(uint32_t *)(u1.raw + 20) < ts.tv_sec) - return 1; + { + uint32_t expires; + memcpy(&expires, u1.raw + 20, sizeof(expires)); + if (expires < ts.tv_sec) + return 1; + } MD5_Init(&ctx); MD5_Update(&ctx, serv->secret, SECRET_LENGTH); @@ -1073,7 +1085,7 @@ static void pppoe_recv_PADI(struct pppoe_serv_t *serv, uint8_t *pack, int size) break; case TAG_PPP_MAX_PAYLOAD: if (ntohs(tag->tag_len) == 2) - ppp_max_payload = ntohs(*(uint16_t *)tag->tag_data); + ppp_max_payload = u_read_be16(tag->tag_data); break; } } @@ -1220,14 +1232,14 @@ static void pppoe_recv_PADR(struct pppoe_serv_t *serv, uint8_t *pack, int size) case TAG_VENDOR_SPECIFIC: if (ntohs(tag->tag_len) < 4) continue; - vendor_id = ntohl(*(uint32_t *)tag->tag_data); + vendor_id = u_read_be32(tag->tag_data); if (vendor_id == VENDOR_ADSL_FORUM) if (conf_tr101) tr101_tag = tag; break; case TAG_PPP_MAX_PAYLOAD: if (ntohs(tag->tag_len) == 2) - ppp_max_payload = ntohs(*(uint16_t *)tag->tag_data); + ppp_max_payload = u_read_be16(tag->tag_data); break; } } diff --git a/accel-pppd/ctrl/pppoe/tr101.c b/accel-pppd/ctrl/pppoe/tr101.c index bb8b845a..06aeff86 100644 --- a/accel-pppd/ctrl/pppoe/tr101.c +++ b/accel-pppd/ctrl/pppoe/tr101.c @@ -8,6 +8,7 @@ #include "log.h" #include "radius.h" #include "memdebug.h" +#include "utils.h" #include "pppoe.h" @@ -75,85 +76,85 @@ static int tr101_send_request(struct pppoe_tag *tr101, struct rad_packet_t *pack case OPT_ACTUAL_DATA_RATE_UP: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Data-Rate-Upstream", u_read_be32(ptr))) return -1; break; case OPT_ACTUAL_DATA_RATE_DOWN: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Data-Rate-Downstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Data-Rate-Downstream", u_read_be32(ptr))) return -1; break; case OPT_MIN_DATA_RATE_UP: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Upstream", u_read_be32(ptr))) return -1; break; case OPT_MIN_DATA_RATE_DOWN: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Downstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Downstream", u_read_be32(ptr))) return -1; break; case OPT_ATT_DATA_RATE_UP: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Attainable-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Attainable-Data-Rate-Upstream", u_read_be32(ptr))) return -1; break; case OPT_ATT_DATA_RATE_DOWN: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Attainable-Data-Rate-Downstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Attainable-Data-Rate-Downstream", u_read_be32(ptr))) return -1; break; case OPT_MAX_DATA_RATE_UP: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Data-Rate-Upstream", u_read_be32(ptr))) return -1; break; case OPT_MAX_DATA_RATE_DOWN: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Data-Rate-Downstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Data-Rate-Downstream", u_read_be32(ptr))) return -1; break; case OPT_MIN_DATA_RATE_UP_LP: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Upstream-Low-Power", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Upstream-Low-Power", u_read_be32(ptr))) return -1; break; case OPT_MIN_DATA_RATE_DOWN_LP: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Downstream-Low-Power", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Downstream-Low-Power", u_read_be32(ptr))) return -1; break; case OPT_MAX_INTERL_DELAY_UP: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Interleaving-Delay-Upstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Interleaving-Delay-Upstream", u_read_be32(ptr))) return -1; break; case OPT_ACTUAL_INTERL_DELAY_UP: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Interleaving-Delay-Upstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Interleaving-Delay-Upstream", u_read_be32(ptr))) return -1; break; case OPT_MAX_INTER_DELAY_DOWN: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Interleaving-Delay-Downstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Interleaving-Delay-Downstream", u_read_be32(ptr))) return -1; break; case OPT_ACTUAL_INTER_DELAY_DOWN: if (len != 4) goto inval; - if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Interleaving-Delay-Downstream", ntohl(*(uint32_t *)ptr))) + if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Interleaving-Delay-Downstream", u_read_be32(ptr))) return -1; break; case ACCESS_LOOP_ENCAP: diff --git a/accel-pppd/extra/ippool.c b/accel-pppd/extra/ippool.c index e935bb4c..28aecd95 100644 --- a/accel-pppd/extra/ippool.c +++ b/accel-pppd/extra/ippool.c @@ -736,10 +736,10 @@ static int session_restore(struct ap_session *ses, struct backup_mod *m) list_for_each_entry(tag, &m->tag_list, entry) { switch (tag->id) { case SES_TAG_IPV4_ADDR: - addr = *(in_addr_t *)tag->data; + memcpy(&addr, tag->data, sizeof(addr)); break; case SES_TAG_IPV4_PEER_ADDR: - peer_addr = *(in_addr_t *)tag->data; + memcpy(&peer_addr, tag->data, sizeof(peer_addr)); break; } } diff --git a/accel-pppd/extra/ipv6pool.c b/accel-pppd/extra/ipv6pool.c index 9a763445..05b84fe8 100644 --- a/accel-pppd/extra/ipv6pool.c +++ b/accel-pppd/extra/ipv6pool.c @@ -293,11 +293,18 @@ static void add_prefix(struct ip6_pool *pool, const char *_val) /* end = start | hostmask(mask) (matches the original generator) */ memcpy(&end, &start, sizeof(end)); - if (mask > 64) - *(uint64_t *)(end.s6_addr + 8) = htobe64(be64toh(*(uint64_t *)(end.s6_addr + 8)) | ((1llu << (128 - mask)) - 1)); + if (mask > 64) { + uint64_t value; + memcpy(&value, end.s6_addr + 8, sizeof(value)); + value = htobe64(be64toh(value) | ((1llu << (128 - mask)) - 1)); + memcpy(end.s6_addr + 8, &value, sizeof(value)); + } else { + uint64_t value; memset(end.s6_addr + 8, 0xff, 8); - *(uint64_t *)end.s6_addr = htobe64(be64toh(*(uint64_t *)end.s6_addr) | ((1llu << (64 - mask)) - 1)); + memcpy(&value, end.s6_addr, sizeof(value)); + value = htobe64(be64toh(value) | ((1llu << (64 - mask)) - 1)); + memcpy(end.s6_addr, &value, sizeof(value)); } { diff --git a/accel-pppd/ifcfg.c b/accel-pppd/ifcfg.c index 4e4a381a..66f5cc6b 100644 --- a/accel-pppd/ifcfg.c +++ b/accel-pppd/ifcfg.c @@ -225,7 +225,7 @@ void __export ap_session_ifdown(struct ap_session *ses) if (ses->ctrl->ppp) { ifr6.ifr6_addr.s6_addr32[0] = htonl(0xfe800000); - *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ses->ipv6->intf_id; + memcpy(ifr6.ifr6_addr.s6_addr + 8, &ses->ipv6->intf_id, sizeof(ses->ipv6->intf_id)); ifr6.ifr6_prefixlen = 64; net->sock6_ioctl(SIOCDIFADDR, &ifr6); } @@ -376,4 +376,4 @@ int __export ap_session_vrf(struct ap_session *ses, const char *vrf_name, int le return 0; } -#endif
\ No newline at end of file +#endif diff --git a/accel-pppd/ipdb.c b/accel-pppd/ipdb.c index 8fc08063..264f67b3 100644 --- a/accel-pppd/ipdb.c +++ b/accel-pppd/ipdb.c @@ -75,18 +75,23 @@ void __export ipdb_put_ipv6_prefix(struct ap_session *ses, struct ipv6db_prefix_ void __export build_ip6_addr(struct ipv6db_addr_t *a, uint64_t intf_id, struct in6_addr *addr) { + uint64_t value; + memcpy(addr, &a->addr, sizeof(*addr)); if (a->prefix_len == 128) return; if (a->prefix_len <= 64) - *(uint64_t *)(addr->s6_addr + 8) = intf_id; - else + memcpy(addr->s6_addr + 8, &intf_id, sizeof(intf_id)); + else { /* prefix_len 65..127 means a shift of up to 63 bits: a plain * int literal 1 is undefined behavior for shifts >= 31, so the * host bits mask must be built from a 64-bit constant */ - *(uint64_t *)(addr->s6_addr + 8) |= intf_id & htobe64((UINT64_C(1) << (128 - a->prefix_len)) - 1); + memcpy(&value, addr->s6_addr + 8, sizeof(value)); + value |= intf_id & htobe64((UINT64_C(1) << (128 - a->prefix_len)) - 1); + memcpy(addr->s6_addr + 8, &value, sizeof(value)); + } } diff --git a/accel-pppd/ipv6/dhcpv6.c b/accel-pppd/ipv6/dhcpv6.c index 4a80bdb9..a0b159cf 100644 --- a/accel-pppd/ipv6/dhcpv6.c +++ b/accel-pppd/ipv6/dhcpv6.c @@ -23,6 +23,7 @@ #include "ipv6_dns.h" #include "events.h" #include "iputils.h" +#include "utils.h" #include "dhcpv6.h" @@ -222,25 +223,28 @@ static void insert_oro(struct dhcpv6_packet *reply, struct dhcpv6_option *opt) { struct dhcpv6_option *opt1; int i, j, dns_count; - uint16_t *ptr; - struct in6_addr addr, *addr_ptr; + uint8_t *ptr; + uint16_t code; + struct in6_addr addr; + uint8_t *addr_ptr; struct in6_addr dns[MAX_DNS_COUNT]; - for (i = ntohs(opt->hdr->len) / 2, ptr = (uint16_t *)opt->hdr->data; i; i--, ptr++) { - if (ntohs(*ptr) == D6_OPTION_DNS_SERVERS) { + for (i = ntohs(opt->hdr->len) / 2, ptr = opt->hdr->data; i; i--, ptr += sizeof(code)) { + code = u_read_be16(ptr); + if (code == D6_OPTION_DNS_SERVERS) { dns_count = ipv6_dns_get(reply->ses, conf_dns, conf_dns_count, dns, MAX_DNS_COUNT); if (dns_count) { opt1 = dhcpv6_option_alloc(reply, D6_OPTION_DNS_SERVERS, dns_count * sizeof(addr)); - for (j = 0, addr_ptr = (struct in6_addr *)opt1->hdr->data; j < dns_count; j++, addr_ptr++) + for (j = 0, addr_ptr = opt1->hdr->data; j < dns_count; j++, addr_ptr += sizeof(addr)) memcpy(addr_ptr, dns + j, sizeof(addr)); } - } else if (ntohs(*ptr) == D6_OPTION_DOMAIN_LIST) { + } else if (code == D6_OPTION_DOMAIN_LIST) { if (conf_dnssl_size) { opt1 = dhcpv6_option_alloc(reply, D6_OPTION_DOMAIN_LIST, conf_dnssl_size); memcpy(opt1->hdr->data, conf_dnssl, conf_dnssl_size); } - } else if (ntohs(*ptr) == D6_OPTION_AFTR_NAME) { + } else if (code == D6_OPTION_AFTR_NAME) { if (conf_aftr_gw_size) { opt1 = dhcpv6_option_alloc(reply, D6_OPTION_AFTR_NAME, conf_aftr_gw_size); memcpy(opt1->hdr->data, conf_aftr_gw, conf_aftr_gw_size); diff --git a/accel-pppd/ipv6/dhcpv6_packet.c b/accel-pppd/ipv6/dhcpv6_packet.c index c0c7bc81..f1c168b6 100644 --- a/accel-pppd/ipv6/dhcpv6_packet.c +++ b/accel-pppd/ipv6/dhcpv6_packet.c @@ -4,6 +4,7 @@ #include "log.h" #include "memdebug.h" +#include "utils.h" #include "dhcpv6.h" @@ -13,7 +14,8 @@ struct dict_option { int code; const char *name; int recv; - int len; + int min_len; + int nested; void (*print)(struct dhcpv6_option *, void (*)(const char *fmt, ...)); }; @@ -34,30 +36,30 @@ static void print_ia_prefix(struct dhcpv6_option *opt, void (*print)(const char static void print_aftr_gw(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)); static struct dict_option known_options[] = { - { D6_OPTION_CLIENTID, "Client-ID", 1, 0, print_clientid }, - { D6_OPTION_SERVERID, "Server-ID", 0, 0, print_clientid }, - { D6_OPTION_IA_NA, "IA-NA", 1, sizeof(struct dhcpv6_opt_ia_na), print_ia_na }, - { D6_OPTION_IA_TA, "IA-TA", 1, sizeof(struct dhcpv6_opt_ia_ta), print_ia_ta }, - { D6_OPTION_IAADDR, "IA-Addr", 1, sizeof(struct dhcpv6_opt_ia_addr), print_ia_addr }, - { D6_OPTION_ORO, "Option-Request", 1, 0, print_oro }, - { D6_OPTION_PREFERENCE, "Preference", 0, 0, print_uint8 }, - { D6_OPTION_ELAPSED_TIME, "Elapsed-Time", 1, 0, print_time }, - { D6_OPTION_RELAY_MSG, "Relay-Message", 1, 0 }, - { D6_OPTION_AUTH, "Auth", 1, 0 }, - { D6_OPTION_PREFERENCE, "Server-Unicast", 0, 0, print_ipv6addr }, - { D6_OPTION_STATUS_CODE, "Status", 0, 0, print_status }, - { D6_OPTION_RAPID_COMMIT, "Rapid-Commit", 1, 0 }, - { D6_OPTION_USER_CLASS, "User-Class", 1, 0 }, - { D6_OPTION_VENDOR_CLASS, "Vendor-Class", 1, 0, print_hex_array }, - { D6_OPTION_VENDOR_SPECIFIC, "Vendor-Specific", 1, 0, print_hex_array }, - { D6_OPTION_INTERFACE_ID, "Interface-ID", 1, 0, print_hex_array }, - { D6_OPTION_RECONF_MSG, "Reconfigure", 0, 0, print_reconf }, - { D6_OPTION_RECONF_ACCEPT, "Reconfigure-Accept", 1, 0 }, - { D6_OPTION_DNS_SERVERS, "DNS", 1, 0, print_ipv6addr_array }, - { D6_OPTION_DOMAIN_LIST, "DNSSL", 1, 0, print_dnssl }, - { D6_OPTION_IA_PD, "IA-PD", 1, sizeof(struct dhcpv6_opt_ia_na), print_ia_na }, - { D6_OPTION_IAPREFIX, "IA-Prefix", 1, sizeof(struct dhcpv6_opt_ia_prefix), print_ia_prefix }, - { D6_OPTION_AFTR_NAME, "AFTR-Name", 1, 0, print_aftr_gw }, + { D6_OPTION_CLIENTID, "Client-ID", 1, sizeof(uint16_t), 0, print_clientid }, + { D6_OPTION_SERVERID, "Server-ID", 0, sizeof(uint16_t), 0, print_clientid }, + { D6_OPTION_IA_NA, "IA-NA", 1, sizeof(struct dhcpv6_opt_ia_na) - sizeof(struct dhcpv6_opt_hdr), 1, print_ia_na }, + { D6_OPTION_IA_TA, "IA-TA", 1, sizeof(struct dhcpv6_opt_ia_ta) - sizeof(struct dhcpv6_opt_hdr), 1, print_ia_ta }, + { D6_OPTION_IAADDR, "IA-Addr", 1, sizeof(struct dhcpv6_opt_ia_addr) - sizeof(struct dhcpv6_opt_hdr), 1, print_ia_addr }, + { D6_OPTION_ORO, "Option-Request", 1, 0, 0, print_oro }, + { D6_OPTION_PREFERENCE, "Preference", 0, sizeof(uint8_t), 0, print_uint8 }, + { D6_OPTION_ELAPSED_TIME, "Elapsed-Time", 1, sizeof(uint16_t), 0, print_time }, + { D6_OPTION_RELAY_MSG, "Relay-Message", 1, sizeof(struct dhcpv6_msg_hdr), 0 }, + { D6_OPTION_AUTH, "Auth", 1, 0, 0 }, + { D6_OPTION_UNICAST, "Server-Unicast", 0, sizeof(struct in6_addr), 0, print_ipv6addr }, + { D6_OPTION_STATUS_CODE, "Status", 0, sizeof(uint16_t), 0, print_status }, + { D6_OPTION_RAPID_COMMIT, "Rapid-Commit", 1, 0, 0 }, + { D6_OPTION_USER_CLASS, "User-Class", 1, 0, 0 }, + { D6_OPTION_VENDOR_CLASS, "Vendor-Class", 1, 0, 0, print_hex_array }, + { D6_OPTION_VENDOR_SPECIFIC, "Vendor-Specific", 1, 0, 0, print_hex_array }, + { D6_OPTION_INTERFACE_ID, "Interface-ID", 1, 0, 0, print_hex_array }, + { D6_OPTION_RECONF_MSG, "Reconfigure", 0, sizeof(uint8_t), 0, print_reconf }, + { D6_OPTION_RECONF_ACCEPT, "Reconfigure-Accept", 1, 0, 0 }, + { D6_OPTION_DNS_SERVERS, "DNS", 1, 0, 0, print_ipv6addr_array }, + { D6_OPTION_DOMAIN_LIST, "DNSSL", 1, 0, 0, print_dnssl }, + { D6_OPTION_IA_PD, "IA-PD", 1, sizeof(struct dhcpv6_opt_ia_na) - sizeof(struct dhcpv6_opt_hdr), 1, print_ia_na }, + { D6_OPTION_IAPREFIX, "IA-Prefix", 1, sizeof(struct dhcpv6_opt_ia_prefix) - sizeof(struct dhcpv6_opt_hdr), 1, print_ia_prefix }, + { D6_OPTION_AFTR_NAME, "AFTR-Name", 1, 0, 0, print_aftr_gw }, { 0 } }; @@ -89,9 +91,14 @@ static void *parse_option(void *ptr, void *endptr, struct list_head *opt_list) break; } - if (dopt->len) { + if (ntohs(opth->len) < dopt->min_len) { + log_warn("dhcpv6: invalid packet received\n"); + return NULL; + } + + if (dopt->nested) { endptr = ptr + sizeof(*opth) + ntohs(opth->len); - ptr += dopt->len; + ptr += sizeof(*opth) + dopt->min_len; while (ptr < endptr) { ptr = parse_option(ptr, endptr, &opt->opt_list); if (!ptr) @@ -109,7 +116,8 @@ struct dhcpv6_packet *dhcpv6_packet_parse(const void *buf, size_t size) struct dhcpv6_opt_hdr *opth; struct dhcpv6_relay *rel; struct dhcpv6_relay_hdr *rhdr; - void *ptr, *endptr; + struct dhcpv6_msg_hdr *inner_hdr; + void *ptr, *endptr, *relay_end, *inner_end; if (size < sizeof(struct dhcpv6_msg_hdr)) { if (conf_verbose) @@ -133,8 +141,6 @@ struct dhcpv6_packet *dhcpv6_packet_parse(const void *buf, size_t size) endptr = ((void *)pkt->hdr) + size; while (pkt->hdr->type == D6_RELAY_FORW) { - struct dhcpv6_msg_hdr *prev_hdr = pkt->hdr; - rhdr = (struct dhcpv6_relay_hdr *)pkt->hdr; if (((void *)rhdr) + sizeof(*rhdr) > endptr) { log_warn("dhcpv6: invalid packet received\n"); @@ -153,27 +159,37 @@ struct dhcpv6_packet *dhcpv6_packet_parse(const void *buf, size_t size) list_add_tail(&rel->entry, &pkt->relay_list); + inner_hdr = NULL; + inner_end = NULL; + relay_end = endptr; ptr = rhdr->data; - while (ptr < endptr) { + while (ptr < relay_end) { opth = ptr; - if (ptr + sizeof(*opth) > endptr || - ptr + sizeof(*opth) + ntohs(opth->len) > endptr) { + if (ptr + sizeof(*opth) > relay_end || + ptr + sizeof(*opth) + ntohs(opth->len) > relay_end) { log_warn("dhcpv6: invalid packet received\n"); goto error; } if (opth->code == htons(D6_OPTION_RELAY_MSG)) { - pkt->hdr = (struct dhcpv6_msg_hdr *)opth->data; - endptr = opth->data + ntohs(opth->len); + if (inner_hdr || ntohs(opth->len) < sizeof(*inner_hdr)) { + log_warn("dhcpv6: invalid packet received\n"); + goto error; + } + inner_hdr = (struct dhcpv6_msg_hdr *)opth->data; + inner_end = opth->data + ntohs(opth->len); } ptr += sizeof(*opth) + ntohs(opth->len); } - if (pkt->hdr == prev_hdr) { + if (!inner_hdr) { log_warn("dhcpv6: invalid packet received\n"); goto error; } + + pkt->hdr = inner_hdr; + endptr = inner_end; } ptr = pkt->hdr->data; @@ -462,26 +478,28 @@ static void print_ia_addr(struct dhcpv6_option *opt, void (*print)(const char *f static void print_oro(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) { - uint16_t *ptr = (uint16_t *)opt->hdr->data; - uint16_t *end_ptr = ptr + ntohs(opt->hdr->len)/2; + uint8_t *ptr = opt->hdr->data; + uint8_t *end_ptr = ptr + ntohs(opt->hdr->len) / 2 * sizeof(uint16_t); struct dict_option *dopt; + uint16_t code; int f = 0; - for (; ptr < end_ptr; ptr++) { + for (; ptr < end_ptr; ptr += sizeof(uint16_t)) { if (f) print(","); else print(" "); + code = u_read_be16(ptr); for (dopt = known_options; dopt->code; dopt++) { - if (ntohs(*ptr) == dopt->code) + if (code == dopt->code) break; } if (dopt->code) print("%s", dopt->name); else - print("%i", ntohs(*ptr)); + print("%i", code); f = 1; } @@ -506,13 +524,10 @@ static void print_uint8(struct dhcpv6_option *opt, void (*print)(const char *fmt static void print_time(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) { - uint16_t val; - - if (ntohs(opt->hdr->len) < sizeof(val)) + if (ntohs(opt->hdr->len) < sizeof(uint16_t)) return; - memcpy(&val, opt->hdr->data, sizeof(val)); - print(" %u", ntohs(val)); + print(" %u", u_read_be16(opt->hdr->data)); } static void print_ipv6addr(struct dhcpv6_option *opt, void (*print)(const char *fmt, ...)) @@ -529,9 +544,9 @@ static void print_ipv6addr_array(struct dhcpv6_option *opt, void (*print)(const char str[INET6_ADDRSTRLEN]; int i; int f = 0; - struct in6_addr *addr = (struct in6_addr *)opt->hdr->data; + uint8_t *addr = opt->hdr->data; - for (i = ntohs(opt->hdr->len) / sizeof(*addr); i; i--, addr++) { + for (i = ntohs(opt->hdr->len) / sizeof(struct in6_addr); i; i--, addr += sizeof(struct in6_addr)) { inet_ntop(AF_INET6, addr, str, sizeof(str)); print("%c%s", f ? ',' : ' ', str); f = 1; diff --git a/accel-pppd/memdebug.c b/accel-pppd/memdebug.c index 5353e572..b3488aaa 100644 --- a/accel-pppd/memdebug.c +++ b/accel-pppd/memdebug.c @@ -42,6 +42,19 @@ struct mem_t static LIST_HEAD(mem_list); static spinlock_t mem_list_lock; +static uint64_t get_tail_magic(const struct mem_t *mem) +{ + uint64_t magic; + + memcpy(&magic, mem->data + mem->size, sizeof(magic)); + return magic; +} + +static void set_tail_magic(struct mem_t *mem) +{ + memcpy(mem->data + mem->size, &mem->magic2, sizeof(mem->magic2)); +} + static struct mem_t *_md_malloc(size_t size, const char *fname, int line) { struct mem_t *mem = malloc(sizeof(*mem) + size + 8); @@ -54,7 +67,7 @@ static struct mem_t *_md_malloc(size_t size, const char *fname, int line) mem->size = size; mem->magic1 = MAGIC1; mem->magic2 = (uint64_t)random() * (uint64_t)random(); - *(uint64_t*)(mem->data + size) = mem->magic2; + set_tail_magic(mem); spin_lock(&mem_list_lock); list_add_tail(&mem->entry, &mem_list); @@ -84,7 +97,7 @@ void __export md_free(void *ptr, const char *fname, int line) abort(); } - if (mem->magic2 != *(uint64_t*)(mem->data + mem->size)) { + if (mem->magic2 != get_tail_magic(mem)) { printf("memory corruption:\nmalloc(%zu) at %s:%i\nfree at %s:%i\n", mem->size, mem->fname, mem->line, fname, line); abort(); @@ -113,7 +126,7 @@ void __export *md_realloc(void *ptr, size_t size, const char *fname, int line) abort(); } - if (mem->magic2 != *(uint64_t*)(mem->data + mem->size)) { + if (mem->magic2 != get_tail_magic(mem)) { printf("memory corruption:\nmalloc(%zu) at %s:%i\nfree at %s:%i\n", mem->size, mem->fname, mem->line, fname, line); abort(); @@ -217,7 +230,7 @@ static void siginfo2(int num) spin_lock(&mem_list_lock); list_for_each_entry(mem, &mem_list, entry) { - if (mem->magic1 != MAGIC1 || mem->magic2 != *(uint64_t*)(mem->data + mem->size)) + if (mem->magic1 != MAGIC1 || mem->magic2 != get_tail_magic(mem)) printf("%s:%i %lu\n", mem->fname, mem->line, (long unsigned)mem->size); } spin_unlock(&mem_list_lock); @@ -233,7 +246,7 @@ void __export md_check(void *ptr) if (mem->magic1 != MAGIC1) abort(); - if (mem->magic2 != *(uint64_t*)(mem->data + mem->size)) + if (mem->magic2 != get_tail_magic(mem)) abort(); } diff --git a/accel-pppd/ppp/ccp_mppe.c b/accel-pppd/ppp/ccp_mppe.c index cb41c0da..5042c8a0 100644 --- a/accel-pppd/ppp/ccp_mppe.c +++ b/accel-pppd/ppp/ccp_mppe.c @@ -10,6 +10,7 @@ #include "ppp_ccp.h" #include "log.h" #include "events.h" +#include "utils.h" #include "memdebug.h" @@ -106,7 +107,7 @@ static int setup_mppe_key(int fd, int transmit, uint8_t *key) memset(buf, 0, sizeof(buf)); buf[0] = CI_MPPE; buf[1] = 6; - *(uint32_t*)(buf + 2) = htonl(MPPE_S | MPPE_H); + u_write_be32(buf + 2, MPPE_S | MPPE_H); if (key) memcpy(buf + 6, key, 16); diff --git a/accel-pppd/ppp/ipv6cp_opt_intfid.c b/accel-pppd/ppp/ipv6cp_opt_intfid.c index cb33f024..5de88932 100644 --- a/accel-pppd/ppp/ipv6cp_opt_intfid.c +++ b/accel-pppd/ppp/ipv6cp_opt_intfid.c @@ -284,12 +284,14 @@ static void ipaddr_print(void (*print)(const char *fmt,...), struct ipv6cp_optio { struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt); struct ipv6cp_opt64_t *opt64 = (struct ipv6cp_opt64_t *)ptr; - struct in6_addr a; + struct in6_addr a = {}; + uint64_t intf_id; if (ptr) - *(uint64_t *)(a.s6_addr + 8) = opt64->val; + intf_id = opt64->val; else - *(uint64_t *)(a.s6_addr + 8) = ipaddr_opt->ppp->ses.ipv6->intf_id; + intf_id = ipaddr_opt->ppp->ses.ipv6->intf_id; + memcpy(a.s6_addr + 8, &intf_id, sizeof(intf_id)); print("<addr %x:%x:%x:%x>", ntohs(a.s6_addr16[4]), ntohs(a.s6_addr16[5]), ntohs(a.s6_addr16[6]), ntohs(a.s6_addr16[7])); } @@ -376,4 +378,3 @@ static void init() } DEFINE_INIT(5, init); - diff --git a/accel-pppd/ppp/ppp_ccp.c b/accel-pppd/ppp/ppp_ccp.c index f9e05e89..2082ca3f 100644 --- a/accel-pppd/ppp/ppp_ccp.c +++ b/accel-pppd/ppp/ppp_ccp.c @@ -387,10 +387,18 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp, uint8_t *data, int size) ccp->ropt_len = size; while (size > 0) { + if (size < sizeof(*hdr)) { + log_ppp_warn("CCP: ConfReq: truncated option header (%i bytes left)\n", size); + return CCP_OPT_FAIL; + } + hdr = (struct ccp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) - break; + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + log_ppp_warn("CCP: ConfReq: invalid length %i of option %i (%i bytes left)\n", + hdr->len, hdr->id, size); + return CCP_OPT_FAIL; + } ropt = _malloc(sizeof(*ropt)); memset(ropt, 0, sizeof(*ropt)); @@ -482,10 +490,17 @@ static int ccp_recv_conf_rej(struct ppp_ccp_t *ccp, uint8_t *data, int size) }*/ while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct ccp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &ccp->options, entry) { if (lopt->id == hdr->id) { @@ -523,10 +538,17 @@ static int ccp_recv_conf_nak(struct ppp_ccp_t *ccp, uint8_t *data, int size) }*/ while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct ccp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &ccp->options, entry) { if (lopt->id == hdr->id) { @@ -566,10 +588,17 @@ static int ccp_recv_conf_ack(struct ppp_ccp_t *ccp, uint8_t *data, int size) }*/ while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct ccp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &ccp->options, entry) { if (lopt->id == hdr->id) { @@ -647,7 +676,7 @@ static void ccp_recv(struct ppp_handler_t*h) } hdr = (struct ccp_hdr_t *)ccp->ppp->buf; - if (ntohs(hdr->len) < PPP_HEADERLEN) { + if (ntohs(hdr->len) < PPP_HEADERLEN || ntohs(hdr->len) > ccp->ppp->buf_size - 2) { log_ppp_warn("CCP: short packet received\n"); return; } @@ -695,8 +724,10 @@ static void ccp_recv(struct ppp_handler_t*h) ppp_fsm_recv_conf_ack(&ccp->fsm); break; case CONFNAK: - ccp_recv_conf_nak(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN); - ppp_fsm_recv_conf_rej(&ccp->fsm); + if (ccp_recv_conf_nak(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN)) + ap_session_terminate(&ccp->ppp->ses, TERM_USER_ERROR, 0); + else + ppp_fsm_recv_conf_rej(&ccp->fsm); break; case CONFREJ: if (ccp_recv_conf_rej(ccp, (uint8_t*)(hdr + 1),ntohs(hdr->len) - PPP_HDRLEN)) diff --git a/accel-pppd/ppp/ppp_ipcp.c b/accel-pppd/ppp/ppp_ipcp.c index 416fba93..2f75542a 100644 --- a/accel-pppd/ppp/ppp_ipcp.c +++ b/accel-pppd/ppp/ppp_ipcp.c @@ -391,10 +391,18 @@ static int ipcp_recv_conf_req(struct ppp_ipcp_t *ipcp, uint8_t *data, int size) ipcp->ropt_len = size; while (size > 0) { + if (size < sizeof(*hdr)) { + log_ppp_warn("IPCP: ConfReq: truncated option header (%i bytes left)\n", size); + return IPCP_OPT_FAIL; + } + hdr = (struct ipcp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) - break; + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + log_ppp_warn("IPCP: ConfReq: invalid length %i of option %i (%i bytes left)\n", + hdr->len, hdr->id, size); + return IPCP_OPT_FAIL; + } ropt = _malloc(sizeof(*ropt)); memset(ropt, 0, sizeof(*ropt)); @@ -503,10 +511,17 @@ static int ipcp_recv_conf_rej(struct ppp_ipcp_t *ipcp, uint8_t *data, int size) }*/ while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct ipcp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &ipcp->options, entry) { if (lopt->id == hdr->id) { @@ -544,10 +559,17 @@ static int ipcp_recv_conf_nak(struct ppp_ipcp_t *ipcp, uint8_t *data, int size) }*/ while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct ipcp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &ipcp->options, entry) { if (lopt->id == hdr->id) { @@ -587,10 +609,17 @@ static int ipcp_recv_conf_ack(struct ppp_ipcp_t *ipcp, uint8_t *data, int size) }*/ while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct ipcp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &ipcp->options, entry) { if (lopt->id == hdr->id) { @@ -671,7 +700,7 @@ static void ipcp_recv(struct ppp_handler_t*h) } hdr = (struct ipcp_hdr_t *)ipcp->ppp->buf; - if (ntohs(hdr->len) < PPP_HEADERLEN) { + if (ntohs(hdr->len) < PPP_HEADERLEN || ntohs(hdr->len) > ipcp->ppp->buf_size - 2) { log_ppp_warn("IPCP: short packet received\n"); return; } @@ -725,8 +754,10 @@ static void ipcp_recv(struct ppp_handler_t*h) ppp_fsm_recv_conf_ack(&ipcp->fsm); break; case CONFNAK: - ipcp_recv_conf_nak(ipcp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN); - ppp_fsm_recv_conf_rej(&ipcp->fsm); + if (ipcp_recv_conf_nak(ipcp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN)) + ap_session_terminate(&ipcp->ppp->ses, TERM_USER_ERROR, 0); + else + ppp_fsm_recv_conf_rej(&ipcp->fsm); break; case CONFREJ: if (ipcp_recv_conf_rej(ipcp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN)) diff --git a/accel-pppd/ppp/ppp_ipv6cp.c b/accel-pppd/ppp/ppp_ipv6cp.c index 7f278daa..370f1d55 100644 --- a/accel-pppd/ppp/ppp_ipv6cp.c +++ b/accel-pppd/ppp/ppp_ipv6cp.c @@ -395,10 +395,18 @@ static int ipv6cp_recv_conf_req(struct ppp_ipv6cp_t *ipv6cp, uint8_t *data, int ipv6cp->ropt_len = size; while (size > 0) { + if (size < sizeof(*hdr)) { + log_ppp_warn("IPV6CP: ConfReq: truncated option header (%i bytes left)\n", size); + return IPV6CP_OPT_FAIL; + } + hdr = (struct ipv6cp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) - break; + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + log_ppp_warn("IPV6CP: ConfReq: invalid length %i of option %i (%i bytes left)\n", + hdr->len, hdr->id, size); + return IPV6CP_OPT_FAIL; + } ropt = _malloc(sizeof(*ropt)); memset(ropt, 0, sizeof(*ropt)); @@ -507,10 +515,17 @@ static int ipv6cp_recv_conf_rej(struct ppp_ipv6cp_t *ipv6cp, uint8_t *data, int }*/ while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct ipv6cp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &ipv6cp->options, entry) { if (lopt->id == hdr->id) { @@ -548,10 +563,17 @@ static int ipv6cp_recv_conf_nak(struct ppp_ipv6cp_t *ipv6cp, uint8_t *data, int }*/ while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct ipv6cp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &ipv6cp->options, entry) { if (lopt->id == hdr->id) { @@ -591,10 +613,17 @@ static int ipv6cp_recv_conf_ack(struct ppp_ipv6cp_t *ipv6cp, uint8_t *data, int }*/ while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct ipv6cp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &ipv6cp->options, entry) { if (lopt->id == hdr->id) { @@ -675,7 +704,7 @@ static void ipv6cp_recv(struct ppp_handler_t*h) } hdr = (struct ipv6cp_hdr_t *)ipv6cp->ppp->buf; - if (ntohs(hdr->len) < PPP_HEADERLEN) { + if (ntohs(hdr->len) < PPP_HEADERLEN || ntohs(hdr->len) > ipv6cp->ppp->buf_size - 2) { log_ppp_warn("IPV6CP: short packet received\n"); return; } @@ -729,8 +758,10 @@ static void ipv6cp_recv(struct ppp_handler_t*h) ppp_fsm_recv_conf_ack(&ipv6cp->fsm); break; case CONFNAK: - ipv6cp_recv_conf_nak(ipv6cp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN); - ppp_fsm_recv_conf_rej(&ipv6cp->fsm); + if (ipv6cp_recv_conf_nak(ipv6cp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN)) + ap_session_terminate(&ipv6cp->ppp->ses, TERM_USER_ERROR, 0); + else + ppp_fsm_recv_conf_rej(&ipv6cp->fsm); break; case CONFREJ: if (ipv6cp_recv_conf_rej(ipv6cp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN)) diff --git a/accel-pppd/ppp/ppp_lcp.c b/accel-pppd/ppp/ppp_lcp.c index ed085b3b..2424ca94 100644 --- a/accel-pppd/ppp/ppp_lcp.c +++ b/accel-pppd/ppp/ppp_lcp.c @@ -370,10 +370,18 @@ static int lcp_recv_conf_req(struct ppp_lcp_t *lcp, uint8_t *data, int size) lcp->ropt_len = size; while (size > 0) { + if (size < sizeof(*hdr)) { + log_ppp_warn("LCP: ConfReq: truncated option header (%i bytes left)\n", size); + return LCP_OPT_FAIL; + } + hdr = (struct lcp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) - break; + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + log_ppp_warn("LCP: ConfReq: invalid length %i of option %i (%i bytes left)\n", + hdr->len, hdr->id, size); + return LCP_OPT_FAIL; + } ropt = _malloc(sizeof(*ropt)); memset(ropt, 0, sizeof(*ropt)); @@ -462,10 +470,17 @@ static int lcp_recv_conf_rej(struct ppp_lcp_t *lcp, uint8_t *data, int size) } while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct lcp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &lcp->options, entry) { if (lopt->id == hdr->id) { @@ -507,10 +522,17 @@ static int lcp_recv_conf_nak(struct ppp_lcp_t *lcp, uint8_t *data, int size) } while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct lcp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt,&lcp->options,entry) { if (lopt->id == hdr->id) { @@ -550,10 +572,17 @@ static int lcp_recv_conf_ack(struct ppp_lcp_t *lcp, uint8_t *data, int size) } while (size > 0) { + if (size < sizeof(*hdr)) { + res = -1; + break; + } + hdr = (struct lcp_opt_hdr_t *)data; - if (!hdr->len || hdr->len > size) + if (hdr->len < sizeof(*hdr) || hdr->len > size) { + res = -1; break; + } list_for_each_entry(lopt, &lcp->options, entry) { if (lopt->id == hdr->id) { @@ -587,7 +616,7 @@ static void lcp_recv_echo_repl(struct ppp_lcp_t *lcp, uint8_t *data, int size) if (conf_ppp_verbose) log_ppp_debug("recv [LCP EchoRep id=%x]\n", lcp->fsm.recv_id); } else { - magic = ntohl(*(uint32_t *)data); + magic = u_read_be32(data); if (conf_ppp_verbose) log_ppp_debug("recv [LCP EchoRep id=%x <magic %08x>]\n", lcp->fsm.recv_id, magic); @@ -746,7 +775,7 @@ static void lcp_recv(struct ppp_handler_t*h) hdr = (struct lcp_hdr_t *)lcp->ppp->buf; len = ntohs(hdr->len); buf_len = lcp->ppp->buf_size; - if (len < PPP_HEADERLEN) { + if (len < PPP_HEADERLEN || len > lcp->ppp->buf_size - 2) { log_ppp_warn("LCP: short packet received\n"); return; } @@ -802,7 +831,10 @@ static void lcp_recv(struct ppp_handler_t*h) } break; case CONFNAK: - lcp_recv_conf_nak(lcp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN); + if (lcp_recv_conf_nak(lcp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN)) { + ap_session_terminate(&lcp->ppp->ses, TERM_USER_ERROR, 0); + break; + } if (lcp->fsm.recv_id != lcp->fsm.id) break; ppp_fsm_recv_conf_rej(&lcp->fsm); @@ -838,7 +870,7 @@ static void lcp_recv(struct ppp_handler_t*h) break; } if (conf_ppp_verbose) - log_ppp_debug("recv [LCP EchoReq id=%x <magic %08x>]\n", hdr->id, ntohl(*(uint32_t*)(hdr + 1))); + log_ppp_debug("recv [LCP EchoReq id=%x <magic %08x>]\n", hdr->id, u_read_be32(hdr + 1)); send_echo_reply(lcp); break; case ECHOREP: @@ -854,11 +886,11 @@ static void lcp_recv(struct ppp_handler_t*h) log_ppp_warn("LCP: short ProtoRej received\n"); break; } - log_ppp_info2("recv [LCP ProtoRej id=%x <%04x>]\n", hdr->id, ntohs(*(uint16_t*)(hdr + 1))); + log_ppp_info2("recv [LCP ProtoRej id=%x <%04x>]\n", hdr->id, u_read_be16(hdr + 1)); } if (len < PPP_HDRLEN + 2 || buf_len < (int)(sizeof(*hdr) + 2)) break; - ppp_recv_proto_rej(lcp->ppp, ntohs(*(uint16_t *)(hdr + 1))); + ppp_recv_proto_rej(lcp->ppp, u_read_be16(hdr + 1)); break; case DISCARDREQ: if (conf_ppp_verbose) { @@ -866,7 +898,7 @@ static void lcp_recv(struct ppp_handler_t*h) log_ppp_warn("LCP: short DiscardReq received\n"); break; } - log_ppp_info2("recv [LCP DiscardReq id=%x <magic %08x>]\n", hdr->id, ntohl(*(uint32_t*)(hdr + 1))); + log_ppp_info2("recv [LCP DiscardReq id=%x <magic %08x>]\n", hdr->id, u_read_be32(hdr + 1)); } break; case IDENT: diff --git a/accel-pppd/radius/backup.c b/accel-pppd/radius/backup.c index 6d4db636..bfca0e49 100644 --- a/accel-pppd/radius/backup.c +++ b/accel-pppd/radius/backup.c @@ -6,6 +6,7 @@ #include "log.h" #include "memdebug.h" +#include "utils.h" #include "backup.h" #include "ap_session_backup.h" @@ -22,6 +23,7 @@ #define RAD_TAG_ACCT_SERVER_ADDR 9 #define RAD_TAG_ACCT_SERVER_PORT 10 #define RAD_TAG_IDLE_TIMEOUT 11 + #define RAD_TAG_ACCT_USERNAME 12 @@ -94,10 +96,10 @@ static void restore_ipv4_addr(struct ap_session *ses) list_for_each_entry(tag, &m->tag_list, entry) { switch (tag->id) { case SES_TAG_IPV4_ADDR: - ses->ipv4->addr = *(in_addr_t *)tag->data; + ses->ipv4->addr = u_read_native32(tag->data); break; case SES_TAG_IPV4_PEER_ADDR: - ses->ipv4->peer_addr = *(in_addr_t *)tag->data; + ses->ipv4->peer_addr = u_read_native32(tag->data); break; } } @@ -121,16 +123,16 @@ void radius_restore_session(struct ap_session *ses, struct radius_pd_t *rpd) list_for_each_entry(tag, &m->tag_list, entry) { switch (tag->id) { case RAD_TAG_INTERIM_INTERVAL: - rpd->acct_interim_interval = *(uint32_t *)tag->data; + rpd->acct_interim_interval = u_read_native32(tag->data); break; case RAD_TAG_INTERIM_JITTER: - rpd->acct_interim_jitter = *(uint32_t *)tag->data; + rpd->acct_interim_jitter = u_read_native32(tag->data); break; case RAD_TAG_SESSION_TIMEOUT: - rpd->session_timeout.expire_tv.tv_sec = *(uint64_t *)tag->data - ses->start_time; + rpd->session_timeout.expire_tv.tv_sec = u_read_native64(tag->data) - ses->start_time; break; case RAD_TAG_IDLE_TIMEOUT: - rpd->idle_timeout.period = (*(uint32_t *)tag->data) * 1000; + rpd->idle_timeout.period = u_read_native32(tag->data) * 1000; break; case RAD_TAG_IPV4_ADDR: ses->ipv4 = &rpd->ipv4_addr; @@ -150,16 +152,16 @@ void radius_restore_session(struct ap_session *ses, struct radius_pd_t *rpd) rpd->attr_state_len = tag->size; break; case RAD_TAG_TERMINATION_ACTION: - rpd->termination_action = *(uint32_t *)tag->data; + rpd->termination_action = u_read_native32(tag->data); break; case RAD_TAG_ACCT_USERNAME: rpd->acct_username = _strndup(tag->data, tag->size); break; case RAD_TAG_ACCT_SERVER_ADDR: - acct_addr = *(in_addr_t *)tag->data; + acct_addr = u_read_native32(tag->data); break; case RAD_TAG_ACCT_SERVER_PORT: - acct_port = *(uint16_t *)tag->data; + acct_port = u_read_native16(tag->data); break; } } @@ -182,4 +184,3 @@ static void init(void) } DEFINE_INIT(100, init); - diff --git a/accel-pppd/radius/packet.c b/accel-pppd/radius/packet.c index c7e91349..4a0ab244 100644 --- a/accel-pppd/radius/packet.c +++ b/accel-pppd/radius/packet.c @@ -24,6 +24,7 @@ #include "mempool.h" #include "radius_p.h" #include "attr_defs.h" +#include "utils.h" #include "memdebug.h" @@ -111,20 +112,20 @@ int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA) *ptr = pack->code; ptr++; *ptr = pack->id; ptr++; - *(uint16_t*)ptr = htons(pack->len); ptr+= 2; + u_write_be16(ptr, pack->len); ptr += 2; memcpy(ptr, RA, 16); ptr+=16; list_for_each_entry(attr, &pack->attrs, entry) { if (attr->vendor) { *ptr = 26; ptr++; *ptr = attr->len + 2 + 6; ptr++; - *(uint32_t *)ptr = htonl(attr->vendor->id); ptr+=4; + u_write_be32(ptr, attr->vendor->id); ptr += 4; } *ptr = attr->attr->id; ptr++; *ptr = attr->len + 2; ptr++; switch(attr->attr->type) { case ATTR_TYPE_INTEGER: - *(uint32_t*)ptr = htonl(attr->val.integer); + u_write_be32(ptr, attr->val.integer); break; case ATTR_TYPE_OCTETS: case ATTR_TYPE_STRING: @@ -136,7 +137,7 @@ int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA) memcpy(ptr, &attr->val, attr->len); break; case ATTR_TYPE_DATE: - *(uint32_t*)ptr = htonl(attr->val.date); + u_write_be32(ptr, attr->val.date); break; case ATTR_TYPE_IPV6PREFIX: ptr[0] = 0; @@ -204,17 +205,22 @@ int rad_packet_recv(int fd, struct rad_packet_t **p, struct sockaddr_in *addr) pack->code = *ptr; ptr++; pack->id = *ptr; ptr++; - pack->len = ntohs(*(uint16_t*)ptr); ptr += 2; + pack->len = u_read_be16(ptr); ptr += 2; - if (pack->len > n) { + if (pack->len < 20 || pack->len > n) { log_ppp_warn("radius:packet: short packet received %i, expected %i\n", pack->len, n); goto out_err; } ptr += 16; - n -= 20; + n = pack->len - 20; while (n>0) { + if (n < 2) { + log_ppp_warn("radius:packet: truncated attribute header received\n"); + goto out_err; + } + id = *ptr; ptr++; len = *ptr - 2; ptr++; if (len < 0) { @@ -230,7 +236,7 @@ int rad_packet_recv(int fd, struct rad_packet_t **p, struct sockaddr_in *addr) log_ppp_warn("radius:packet: vendor attribute too short (%i)\n", len); goto out_err; } - vendor_id = ntohl(*(uint32_t *)ptr); + vendor_id = u_read_be32(ptr); vendor = rad_dict_find_vendor_id(vendor_id); if (vendor) { if (len < 4 + vendor->tag + vendor->len) { @@ -240,14 +246,14 @@ int rad_packet_recv(int fd, struct rad_packet_t **p, struct sockaddr_in *addr) ptr += 4; if (vendor->tag == 2) - id = (uint16_t)ntohs(*(uint16_t *)ptr); + id = u_read_be16(ptr); else id = *ptr; ptr += vendor->tag; if (vendor->len == 2) - len = (uint16_t)ntohs(*(uint16_t *)ptr); + len = u_read_be16(ptr); else len = *ptr; @@ -300,15 +306,15 @@ int rad_packet_recv(int fd, struct rad_packet_t **p, struct sockaddr_in *addr) break; } if (len == 4) - attr->val.integer = ntohl(*(uint32_t*)ptr); + attr->val.integer = u_read_be32(ptr); else if (len == 2) - attr->val.integer = ntohs(*(uint16_t*)ptr); + attr->val.integer = u_read_be16(ptr); else if (len == 1) attr->val.integer = *ptr; break; case ATTR_TYPE_DATE: if (len == 4) - attr->val.integer = ntohl(*(uint32_t*)ptr); + attr->val.integer = u_read_be32(ptr); else log_ppp_warn("radius:packet: attribute %s has invalid length %i (must be 4)\n", da->name, len); break; diff --git a/accel-pppd/session_backup.c b/accel-pppd/session_backup.c index dea5b600..2873136f 100644 --- a/accel-pppd/session_backup.c +++ b/accel-pppd/session_backup.c @@ -59,6 +59,8 @@ static int session_save(struct ap_session *ses, struct backup_mod *m) static int session_restore(struct ap_session *ses, struct backup_mod *m) { struct backup_tag *t; + time_t start_time; + uint32_t ifindex; list_for_each_entry(t, &m->tag_list, entry) { switch(t->id) { @@ -79,11 +81,14 @@ static int session_restore(struct ap_session *ses, struct backup_mod *m) ses->ifname[t->size] = 0; break; case SES_TAG_START_TIME: - ses->start_time = *(time_t *)t->data; + memcpy(&start_time, t->data, sizeof(start_time)); + ses->start_time = start_time; break; case SES_TAG_IFINDEX: - if (ses->backup->internal) - ses->ifindex = *(uint32_t *)t->data; + if (ses->backup->internal) { + memcpy(&ifindex, t->data, sizeof(ifindex)); + ses->ifindex = ifindex; + } break; /*case PPP_TAG_FD: ses->fd = *(int *)t->data; diff --git a/accel-pppd/utils.h b/accel-pppd/utils.h index 63c1db0d..7c62422c 100644 --- a/accel-pppd/utils.h +++ b/accel-pppd/utils.h @@ -1,13 +1,86 @@ #ifndef __UTILS_H #define __UTILS_H +#include <endian.h> #include <netinet/in.h> #include <stdint.h> +#include <string.h> #ifndef min #define min(x, y) ((x) < (y) ? (x) : (y)) #endif +/* + * Fixed-size memcpy() lets the compiler emit efficient unaligned accesses on + * architectures that support them without imposing alignment or aliasing + * requirements on callers. + */ +static inline uint16_t u_read_be16(const void *ptr) +{ + uint16_t value; + + memcpy(&value, ptr, sizeof(value)); + return ntohs(value); +} + +static inline uint32_t u_read_be32(const void *ptr) +{ + uint32_t value; + + memcpy(&value, ptr, sizeof(value)); + return ntohl(value); +} + +static inline uint64_t u_read_be64(const void *ptr) +{ + uint64_t value; + + memcpy(&value, ptr, sizeof(value)); + return be64toh(value); +} + +static inline void u_write_be16(void *ptr, uint16_t value) +{ + value = htons(value); + memcpy(ptr, &value, sizeof(value)); +} + +static inline void u_write_be32(void *ptr, uint32_t value) +{ + value = htonl(value); + memcpy(ptr, &value, sizeof(value)); +} + +static inline void u_write_be64(void *ptr, uint64_t value) +{ + value = htobe64(value); + memcpy(ptr, &value, sizeof(value)); +} + +static inline uint16_t u_read_native16(const void *ptr) +{ + uint16_t value; + + memcpy(&value, ptr, sizeof(value)); + return value; +} + +static inline uint32_t u_read_native32(const void *ptr) +{ + uint32_t value; + + memcpy(&value, ptr, sizeof(value)); + return value; +} + +static inline uint64_t u_read_native64(const void *ptr) +{ + uint64_t value; + + memcpy(&value, ptr, sizeof(value)); + return value; +} + char *u_ip6str(const struct in6_addr *addr, char *buf); char *u_ip4str(const struct in_addr *addr, char *buf); |
