source: bootcd/isolinux/syslinux-6.03/com32/lib/dhcpunpack.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 2.4 KB
Line 
1#define _GNU_SOURCE             /* For strnlen() */
2#include <stdlib.h>
3#include <errno.h>
4#include <string.h>
5// #include <arpa/inet.h>
6#include <netinet/in.h>
7
8// #include "dhcp.h"
9#include <dhcp.h>
10
11/*
12 * Unpack DHCP options from a field.  Assumes opt is pre-initalized
13 * (to all zero in the common case.)
14 */
15int dhcp_unpack_field(const void *field, size_t len,
16                      struct dhcp_option opt[256])
17{
18        const uint8_t *p = field;
19        int err = 0;
20
21        while (len > 1) {
22                uint8_t op;
23                size_t xlen;
24
25                op = *p++; len--;
26                if (op == 0)
27                        continue;
28                else if (op == 255)
29                        break;
30               
31                xlen = *p++; len--;
32                if (xlen > len)
33                        break;
34                if (opt[op].len < 0)
35                        opt[op].len = 0;
36                if (xlen) {
37                        opt[op].data = realloc(opt[op].data,
38                                               opt[op].len + xlen + 1);
39                        if (!opt[op].data) {
40                                err = ENOMEM;
41                                continue;
42                        }
43                        memcpy((char *)opt[op].data + opt[op].len, p, xlen);
44                        opt[op].len += xlen;
45                        /* Null-terminate as a courtesy to users */
46                        *((char *)opt[op].data + opt[op].len) = 0;
47                        p += xlen;
48                        len -= xlen;
49                }
50        }
51
52        return err;
53}
54
55/*
56 * Unpack a DHCP packet, with overload support.  Do not use this
57 * to unpack an encapsulated option set.
58 */
59int dhcp_unpack_packet(const void *packet, size_t len,
60                       struct dhcp_option opt[256])
61{
62        const struct dhcp_packet *pkt = packet;
63        int err;
64        uint8_t overload;
65        int i;
66
67        if (len < 240 || pkt->magic != htonl(DHCP_VENDOR_MAGIC))
68                return EINVAL;  /* Bogus packet */
69       
70        for (i = 0; i < 256; i++) {
71                opt[i].len = -1; /* Option not present */
72                opt[i].data = NULL;
73        }
74       
75        err = dhcp_unpack_field(pkt->options, len-240, opt);
76
77        overload = 0;
78        if (opt[52].len == 1) {
79                overload = *(uint8_t *)opt[52].data;
80                free(opt[52].data);
81                opt[52].len = -1;
82                opt[52].data = NULL;
83        }
84
85        if (overload & 1) {
86                err |= dhcp_unpack_field(pkt->file, 128, opt);
87        } else {
88                opt[67].len  = strnlen((const char *)pkt->file, 128);
89                if (opt[67].len) {
90                        opt[67].data = malloc(opt[67].len + 1);
91                        if (opt[67].data) {
92                                memcpy(opt[67].data, pkt->file, opt[67].len);
93                                *((char *)opt[67].data + opt[67].len) = 0;
94                        } else {
95                                err |= ENOMEM;
96                        }
97                }
98        }
99
100        if (overload & 2) {
101                err |= dhcp_unpack_field(pkt->sname, 64, opt);
102        } else {
103                opt[66].len  = strnlen((const char *)pkt->sname, 64);
104                if (opt[66].len) {
105                        opt[66].data = malloc(opt[66].len + 1);
106                        if (opt[66].data) {
107                                memcpy(opt[66].data, pkt->file, opt[66].len);
108                                *((char *)opt[66].data + opt[66].len) = 0;
109                        } else {
110                                err |= ENOMEM;
111                        }
112                }
113        }
114
115        return err;
116}
Note: See TracBrowser for help on using the repository browser.