source: bootcd/isolinux/syslinux-6.03/com32/lib/dhcppack.c @ 26ffad7

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

bootstuff

  • Property mode set to 100644
File size: 3.3 KB
Line 
1#include <stdlib.h>
2#include <errno.h>
3#include <string.h>
4// #include <arpa/inet.h>
5#include <netinet/in.h>
6
7// #include "dhcp.h"
8#include <dhcp.h>
9
10/*
11 * Pack DHCP options into an option field, without overload support.
12 * On return, len contains the number of active bytes, and the full
13 * field is zero-padded.
14 *
15 * Options which are successfully placed have their length zeroed out.
16 */
17static int dhcp_pack_field_zero(void *field, size_t *len,
18                                struct dhcp_option opt[256])
19{
20        int i;
21        size_t xlen, plen;
22        const uint8_t *p;
23        uint8_t *q = field;
24        size_t spc = *len;
25        int err = 0;
26
27        if (!*len)
28                return ENOSPC;
29
30        for (i = 1; i < 255; i++) {
31                if (opt[i].len < 0)
32                        continue;
33
34                /* We need to handle the 0 case as well as > 255 */
35                if (opt[i].len <= 255)
36                        xlen = opt[i].len + 2;
37                else
38                        xlen = opt[i].len + 2*((opt[i].len+254)/255);
39
40                p = opt[i].data;
41
42                if (xlen >= spc) {
43                        /* This option doesn't fit... */
44                        err++;
45                        continue;
46                }
47
48                xlen = opt[i].len;
49                do {
50                        *q++ = i;
51                        *q++ = plen = xlen > 255 ? 255 : xlen;
52                        if (plen)
53                                memcpy(q, p, plen);
54                        q += plen;
55                        p += plen;
56                        spc -= plen+2;
57                        xlen -= plen;
58                } while (xlen);
59
60                opt[i].len = -1;
61        }
62
63        *q++ = 255;             /* End marker */
64        memset(q, 0, spc);      /* Zero-pad the rest of the field */
65       
66        *len = xlen = q - (uint8_t *)field;
67        return err;
68}
69
70/*
71 * Pack DHCP options into an option field, without overload support.
72 * On return, len contains the number of active bytes, and the full
73 * field is zero-padded.
74 *
75 * Use this to encode encapsulated option fields.
76 */
77int dhcp_pack_field(void *field, size_t *len,
78                    struct dhcp_option opt[256])
79{
80        struct dhcp_option ox[256];
81       
82        memcpy(ox, opt, sizeof ox);
83        return dhcp_pack_field_zero(field, len, ox);
84}
85
86/*
87 * Pack DHCP options into a packet.
88 * Apply overloading if (and only if) the "file" or "sname" option
89 * doesn't fit in the respective dedicated fields.
90 */
91int dhcp_pack_packet(void *packet, size_t *len,
92                     const struct dhcp_option opt[256])
93{
94        struct dhcp_packet *pkt = packet;
95        size_t spc = *len;
96        uint8_t overload;
97        struct dhcp_option ox[256];
98        uint8_t *q;
99        int err;
100
101        if (spc < sizeof(struct dhcp_packet))
102                return ENOSPC;  /* Buffer impossibly small */
103       
104        pkt->magic = htonl(DHCP_VENDOR_MAGIC);
105
106        memcpy(ox, opt, sizeof ox);
107
108        /* Figure out if we should do overloading or not */
109        overload = 0;
110
111        if (opt[67].len > 128)
112                overload |= 1;
113        else
114                ox[67].len = -1;
115
116        if (opt[66].len > 64)
117                overload |= 2;
118        else
119                ox[66].len = -1;
120
121        /* Kill any passed-in overload option */
122        ox[52].len = -1;
123
124        q = pkt->options;
125        spc -= 240;
126
127        /* Force option 53 (DHCP packet type) first */
128        if (ox[53].len == 1) {
129                *q++ = 53;
130                *q++ = 1;
131                *q++ = *(uint8_t *)ox[53].data;
132                spc -= 3;
133                ox[53].len = -1;
134        }
135
136        /* Follow with the overload option, if applicable */
137        if (overload) {
138                *q++ = 52;
139                *q++ = 1;
140                *q++ = overload;
141                spc -= 3;
142        }
143
144        err = dhcp_pack_field_zero(q, &spc, ox);
145        *len = spc + (q-(uint8_t *)packet);
146
147        if (overload & 1) {
148                spc = 128;
149                err = dhcp_pack_field_zero(pkt->file, &spc, ox);
150        } else {
151                memset(pkt->file, 0, 128);
152                if (opt[67].len > 0)
153                        memcpy(pkt->file, opt[67].data, opt[67].len);
154        }
155
156        if (overload & 2) {
157                spc = 64;
158                err = dhcp_pack_field_zero(pkt->sname, &spc, ox);
159        } else {
160                memset(pkt->sname, 0, 64);
161                if (opt[66].len > 0)
162                        memcpy(pkt->sname, opt[66].data, opt[66].len);
163        }
164
165        return err;
166}
Note: See TracBrowser for help on using the repository browser.