1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <string.h>
21: #include <netinet/in.h>
22: #include <netinet/ip6.h>
23:
24:
25:
26:
27:
28:
29:
30:
31:
32: int
33: inet6_opt_init (void *extbuf, socklen_t extlen)
34: {
35: if (extbuf != NULL)
36: {
37: if (extlen <= 0 || (extlen % 8) != 0)
38: return -1;
39:
40:
41: struct ip6_hbh *extp = (struct ip6_hbh *) extbuf;
42: extp->ip6h_len = extlen / 8;
43: }
44:
45: return sizeof (struct ip6_hbh);
46: }
47:
48:
49: static void
50: add_padding (uint8_t *extbuf, int offset, int npad)
51: {
52: if (npad == 1)
53: extbuf[offset] = IP6OPT_PAD1;
54: else if (npad > 0)
55: {
56: struct ip6_opt *pad_opt = (struct ip6_opt *) (extbuf + offset);
57:
58: pad_opt->ip6o_type = IP6OPT_PADN;
59: pad_opt->ip6o_len = npad - sizeof (struct ip6_opt);
60:
61: memset (pad_opt + 1, '\0', pad_opt->ip6o_len);
62: }
63: }
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76: int
77: inet6_opt_append (void *extbuf, socklen_t extlen, int offset, uint8_t type,
78: socklen_t len, uint8_t align, void **databufp)
79: {
80:
81: if (offset < sizeof (struct ip6_hbh))
82: return -1;
83:
84:
85: if (type == IP6OPT_PAD1 || type == IP6OPT_PADN)
86: return -1;
87:
88:
89: if (len > 255)
90: return -1;
91:
92:
93:
94: if (align == 0 || align > 8 || (align & (align - 1)) != 0 || align > len)
95: return -1;
96:
97:
98:
99:
100:
101:
102: int data_offset = offset + sizeof (struct ip6_opt);
103: int npad = (align - data_offset % align) & (align - 1);
104:
105: if (extbuf != NULL)
106: {
107:
108: if (data_offset + npad + len > extlen)
109: return -1;
110:
111: add_padding (extbuf, offset, npad);
112:
113: offset += npad;
114:
115:
116: struct ip6_opt *opt = (struct ip6_opt *) ((uint8_t *) extbuf + offset);
117:
118: opt->ip6o_type = type;
119: opt->ip6o_len = len;
120:
121: *databufp = opt + 1;
122: }
123: else
124: offset += npad;
125:
126: return offset + sizeof (struct ip6_opt) + len;
127: }
128:
129:
130:
131:
132:
133:
134:
135:
136: int
137: inet6_opt_finish (void *extbuf, socklen_t extlen, int offset)
138: {
139:
140: if (offset < sizeof (struct ip6_hbh))
141: return -1;
142:
143:
144: int npad = (8 - (offset & 7)) & 7;
145:
146: if (extbuf != NULL)
147: {
148:
149: if (offset + npad > extlen)
150: return -1;
151:
152: add_padding (extbuf, offset, npad);
153: }
154:
155: return offset + npad;
156: }
157:
158:
159:
160:
161:
162:
163:
164:
165:
166: int
167: inet6_opt_set_val (void *databuf, int offset, void *val, socklen_t vallen)
168: {
169: memcpy ((uint8_t *) databuf + offset, val, vallen);
170:
171: return offset + vallen;
172: }
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183: int
184: inet6_opt_next (void *extbuf, socklen_t extlen, int offset, uint8_t *typep,
185: socklen_t *lenp, void **databufp)
186: {
187: if (offset == 0)
188: offset = sizeof (struct ip6_hbh);
189: else if (offset < sizeof (struct ip6_hbh))
190: return -1;
191:
192: while (offset < extlen)
193: {
194: struct ip6_opt *opt = (struct ip6_opt *) ((uint8_t *) extbuf + offset);
195:
196: if (opt->ip6o_type == IP6OPT_PAD1)
197:
198: ++offset;
199: else if (opt->ip6o_type == IP6OPT_PADN)
200: offset += sizeof (struct ip6_opt) + opt->ip6o_len;
201: else
202: {
203:
204: offset += sizeof (struct ip6_opt) + opt->ip6o_len;
205: if (offset > extlen)
206: return -1;
207:
208: *typep = opt->ip6o_type;
209: *lenp = opt->ip6o_len;
210: *databufp = opt + 1;
211: return offset;
212: }
213: }
214:
215: return -1;
216: }
217:
218:
219:
220:
221:
222:
223:
224:
225: int
226: inet6_opt_find (void *extbuf, socklen_t extlen, int offset, uint8_t type,
227: socklen_t *lenp, void **databufp)
228: {
229: if (offset == 0)
230: offset = sizeof (struct ip6_hbh);
231: else if (offset < sizeof (struct ip6_hbh))
232: return -1;
233:
234: while (offset < extlen)
235: {
236: struct ip6_opt *opt = (struct ip6_opt *) ((uint8_t *) extbuf + offset);
237:
238: if (opt->ip6o_type == IP6OPT_PAD1)
239: {
240:
241: ++offset;
242: if (type == IP6OPT_PAD1)
243: {
244: *lenp = 0;
245: *databufp = (uint8_t *) extbuf + offset;
246: return offset;
247: }
248: }
249: else if (opt->ip6o_type != type)
250: offset += sizeof (struct ip6_opt) + opt->ip6o_len;
251: else
252: {
253:
254: offset += sizeof (struct ip6_opt) + opt->ip6o_len;
255: if (offset > extlen)
256: return -1;
257:
258: *lenp = opt->ip6o_len;
259: *databufp = opt + 1;
260: return offset;
261: }
262: }
263:
264: return -1;
265: }
266:
267:
268:
269:
270:
271:
272: int
273: inet6_opt_get_val (void *databuf, int offset, void *val, socklen_t vallen)
274: {
275: memcpy (val, (uint8_t *) databuf + offset, vallen);
276:
277: return offset + vallen;
278: }