]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_mpls_openbsd.c
bgpd: Refactor subgroup_announce_table() to reuse an existing helpers
[mirror_frr.git] / zebra / zebra_mpls_openbsd.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2016 by Open Source Routing.
4 */
5
6 #include <zebra.h>
7
8 #ifdef OPEN_BSD
9
10 #include <netmpls/mpls.h>
11 #include "zebra/rt.h"
12 #include "zebra/zebra_mpls.h"
13 #include "zebra/debug.h"
14 #include "zebra/zebra_errors.h"
15 #include "zebra/zebra_router.h"
16
17 #include "privs.h"
18 #include "prefix.h"
19 #include "interface.h"
20 #include "log.h"
21 #include "lib_errors.h"
22
23 extern struct zebra_privs_t zserv_privs;
24
25 struct {
26 uint32_t rtseq;
27 int fd;
28 int ioctl_fd;
29 } kr_state;
30
31 static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
32 const struct zebra_nhlfe *nhlfe)
33 {
34 struct iovec iov[5];
35 struct rt_msghdr hdr;
36 struct sockaddr_mpls sa_label_in, sa_label_out;
37 struct sockaddr_in nexthop;
38 int iovcnt = 0;
39 int ret;
40
41 if (IS_ZEBRA_DEBUG_KERNEL)
42 zlog_debug("%s: 0x%x, label=%u", __func__, action, in_label);
43
44 /* initialize header */
45 memset(&hdr, 0, sizeof(hdr));
46 hdr.rtm_version = RTM_VERSION;
47
48 hdr.rtm_type = action;
49 hdr.rtm_flags = RTF_UP;
50 hdr.rtm_fmask = RTF_MPLS;
51 hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */
52 hdr.rtm_msglen = sizeof(hdr);
53 hdr.rtm_hdrlen = sizeof(struct rt_msghdr);
54 hdr.rtm_priority = 0;
55 /* adjust iovec */
56 iov[iovcnt].iov_base = &hdr;
57 iov[iovcnt++].iov_len = sizeof(hdr);
58
59 /* in label */
60 memset(&sa_label_in, 0, sizeof(sa_label_in));
61 sa_label_in.smpls_len = sizeof(sa_label_in);
62 sa_label_in.smpls_family = AF_MPLS;
63 sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET);
64 /* adjust header */
65 hdr.rtm_flags |= RTF_MPLS | RTF_MPATH;
66 hdr.rtm_addrs |= RTA_DST;
67 hdr.rtm_msglen += sizeof(sa_label_in);
68 /* adjust iovec */
69 iov[iovcnt].iov_base = &sa_label_in;
70 iov[iovcnt++].iov_len = sizeof(sa_label_in);
71
72 /* nexthop */
73 memset(&nexthop, 0, sizeof(nexthop));
74 nexthop.sin_len = sizeof(nexthop);
75 nexthop.sin_family = AF_INET;
76 nexthop.sin_addr = nhlfe->nexthop->gate.ipv4;
77 /* adjust header */
78 hdr.rtm_flags |= RTF_GATEWAY;
79 hdr.rtm_addrs |= RTA_GATEWAY;
80 hdr.rtm_msglen += sizeof(nexthop);
81 /* adjust iovec */
82 iov[iovcnt].iov_base = &nexthop;
83 iov[iovcnt++].iov_len = sizeof(nexthop);
84
85 /* If action is RTM_DELETE we have to get rid of MPLS infos */
86 if (action != RTM_DELETE) {
87 memset(&sa_label_out, 0, sizeof(sa_label_out));
88 sa_label_out.smpls_len = sizeof(sa_label_out);
89 sa_label_out.smpls_family = AF_MPLS;
90 sa_label_out.smpls_label =
91 htonl(nhlfe->nexthop->nh_label->label[0]
92 << MPLS_LABEL_OFFSET);
93 /* adjust header */
94 hdr.rtm_addrs |= RTA_SRC;
95 hdr.rtm_flags |= RTF_MPLS;
96 hdr.rtm_msglen += sizeof(sa_label_out);
97 /* adjust iovec */
98 iov[iovcnt].iov_base = &sa_label_out;
99 iov[iovcnt++].iov_len = sizeof(sa_label_out);
100
101 if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL)
102 hdr.rtm_mpls = MPLS_OP_POP;
103 else
104 hdr.rtm_mpls = MPLS_OP_SWAP;
105 }
106
107 frr_with_privs(&zserv_privs) {
108 ret = writev(kr_state.fd, iov, iovcnt);
109 }
110
111 if (ret == -1)
112 flog_err_sys(EC_LIB_SOCKET, "%s: %s", __func__,
113 safe_strerror(errno));
114
115 return ret;
116 }
117
118 #if !defined(ROUNDUP)
119 #define ROUNDUP(a) \
120 (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a))
121 #endif
122
123 static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
124 const struct zebra_nhlfe *nhlfe)
125 {
126 struct iovec iov[5];
127 struct rt_msghdr hdr;
128 struct sockaddr_mpls sa_label_in, sa_label_out;
129 struct pad {
130 struct sockaddr_in6 addr;
131 char pad[sizeof(long)]; /* thank you IPv6 */
132 } nexthop;
133 int iovcnt = 0;
134 int ret;
135
136 if (IS_ZEBRA_DEBUG_KERNEL)
137 zlog_debug("%s: 0x%x, label=%u", __func__, action, in_label);
138
139 /* initialize header */
140 memset(&hdr, 0, sizeof(hdr));
141 hdr.rtm_version = RTM_VERSION;
142
143 hdr.rtm_type = action;
144 hdr.rtm_flags = RTF_UP;
145 hdr.rtm_fmask = RTF_MPLS;
146 hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */
147 hdr.rtm_msglen = sizeof(hdr);
148 hdr.rtm_hdrlen = sizeof(struct rt_msghdr);
149 hdr.rtm_priority = 0;
150 /* adjust iovec */
151 iov[iovcnt].iov_base = &hdr;
152 iov[iovcnt++].iov_len = sizeof(hdr);
153
154 /* in label */
155 memset(&sa_label_in, 0, sizeof(sa_label_in));
156 sa_label_in.smpls_len = sizeof(sa_label_in);
157 sa_label_in.smpls_family = AF_MPLS;
158 sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET);
159 /* adjust header */
160 hdr.rtm_flags |= RTF_MPLS | RTF_MPATH;
161 hdr.rtm_addrs |= RTA_DST;
162 hdr.rtm_msglen += sizeof(sa_label_in);
163 /* adjust iovec */
164 iov[iovcnt].iov_base = &sa_label_in;
165 iov[iovcnt++].iov_len = sizeof(sa_label_in);
166
167 /* nexthop */
168 memset(&nexthop, 0, sizeof(nexthop));
169 nexthop.addr.sin6_len = sizeof(struct sockaddr_in6);
170 nexthop.addr.sin6_family = AF_INET6;
171 nexthop.addr.sin6_addr = nhlfe->nexthop->gate.ipv6;
172 if (IN6_IS_ADDR_LINKLOCAL(&nexthop.addr.sin6_addr)) {
173 uint16_t tmp16;
174 struct sockaddr_in6 *sin6 = &nexthop.addr;
175
176 nexthop.addr.sin6_scope_id = nhlfe->nexthop->ifindex;
177
178 memcpy(&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof(tmp16));
179 tmp16 = htons(sin6->sin6_scope_id);
180 memcpy(&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof(tmp16));
181 sin6->sin6_scope_id = 0;
182 }
183
184 /* adjust header */
185 hdr.rtm_flags |= RTF_GATEWAY;
186 hdr.rtm_addrs |= RTA_GATEWAY;
187 hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6));
188 /* adjust iovec */
189 iov[iovcnt].iov_base = &nexthop;
190 iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
191
192 /* If action is RTM_DELETE we have to get rid of MPLS infos */
193 if (action != RTM_DELETE) {
194 memset(&sa_label_out, 0, sizeof(sa_label_out));
195 sa_label_out.smpls_len = sizeof(sa_label_out);
196 sa_label_out.smpls_family = AF_MPLS;
197 sa_label_out.smpls_label =
198 htonl(nhlfe->nexthop->nh_label->label[0]
199 << MPLS_LABEL_OFFSET);
200 /* adjust header */
201 hdr.rtm_addrs |= RTA_SRC;
202 hdr.rtm_flags |= RTF_MPLS;
203 hdr.rtm_msglen += sizeof(sa_label_out);
204 /* adjust iovec */
205 iov[iovcnt].iov_base = &sa_label_out;
206 iov[iovcnt++].iov_len = sizeof(sa_label_out);
207
208 if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL)
209 hdr.rtm_mpls = MPLS_OP_POP;
210 else
211 hdr.rtm_mpls = MPLS_OP_SWAP;
212 }
213
214 frr_with_privs(&zserv_privs) {
215 ret = writev(kr_state.fd, iov, iovcnt);
216 }
217
218 if (ret == -1)
219 flog_err_sys(EC_LIB_SOCKET, "%s: %s", __func__,
220 safe_strerror(errno));
221
222 return ret;
223 }
224
225 static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx)
226 {
227 const struct nhlfe_list_head *head;
228 const struct zebra_nhlfe *nhlfe;
229 const struct nexthop *nexthop = NULL;
230 unsigned int nexthop_num = 0;
231 int action;
232
233 switch (dplane_ctx_get_op(ctx)) {
234 case DPLANE_OP_LSP_DELETE:
235 action = RTM_DELETE;
236 break;
237 case DPLANE_OP_LSP_INSTALL:
238 action = RTM_ADD;
239 break;
240 case DPLANE_OP_LSP_UPDATE:
241 action = RTM_CHANGE;
242 break;
243 case DPLANE_OP_NONE:
244 case DPLANE_OP_ROUTE_INSTALL:
245 case DPLANE_OP_ROUTE_UPDATE:
246 case DPLANE_OP_ROUTE_DELETE:
247 case DPLANE_OP_ROUTE_NOTIFY:
248 case DPLANE_OP_NH_INSTALL:
249 case DPLANE_OP_NH_UPDATE:
250 case DPLANE_OP_NH_DELETE:
251 case DPLANE_OP_LSP_NOTIFY:
252 case DPLANE_OP_PW_INSTALL:
253 case DPLANE_OP_PW_UNINSTALL:
254 case DPLANE_OP_SYS_ROUTE_ADD:
255 case DPLANE_OP_SYS_ROUTE_DELETE:
256 case DPLANE_OP_ADDR_INSTALL:
257 case DPLANE_OP_ADDR_UNINSTALL:
258 case DPLANE_OP_MAC_INSTALL:
259 case DPLANE_OP_MAC_DELETE:
260 case DPLANE_OP_NEIGH_INSTALL:
261 case DPLANE_OP_NEIGH_UPDATE:
262 case DPLANE_OP_NEIGH_DELETE:
263 case DPLANE_OP_VTEP_ADD:
264 case DPLANE_OP_VTEP_DELETE:
265 case DPLANE_OP_RULE_ADD:
266 case DPLANE_OP_RULE_DELETE:
267 case DPLANE_OP_RULE_UPDATE:
268 case DPLANE_OP_NEIGH_DISCOVER:
269 case DPLANE_OP_BR_PORT_UPDATE:
270 case DPLANE_OP_IPTABLE_ADD:
271 case DPLANE_OP_IPTABLE_DELETE:
272 case DPLANE_OP_IPSET_ADD:
273 case DPLANE_OP_IPSET_DELETE:
274 case DPLANE_OP_IPSET_ENTRY_ADD:
275 case DPLANE_OP_IPSET_ENTRY_DELETE:
276 case DPLANE_OP_NEIGH_IP_INSTALL:
277 case DPLANE_OP_NEIGH_IP_DELETE:
278 case DPLANE_OP_NEIGH_TABLE_UPDATE:
279 case DPLANE_OP_GRE_SET:
280 case DPLANE_OP_INTF_ADDR_ADD:
281 case DPLANE_OP_INTF_ADDR_DEL:
282 case DPLANE_OP_INTF_NETCONFIG:
283 case DPLANE_OP_INTF_INSTALL:
284 case DPLANE_OP_INTF_UPDATE:
285 case DPLANE_OP_INTF_DELETE:
286 case DPLANE_OP_TC_QDISC_INSTALL:
287 case DPLANE_OP_TC_QDISC_UNINSTALL:
288 case DPLANE_OP_TC_CLASS_ADD:
289 case DPLANE_OP_TC_CLASS_DELETE:
290 case DPLANE_OP_TC_CLASS_UPDATE:
291 case DPLANE_OP_TC_FILTER_ADD:
292 case DPLANE_OP_TC_FILTER_DELETE:
293 case DPLANE_OP_TC_FILTER_UPDATE:
294 return -1;
295 }
296
297 head = dplane_ctx_get_nhlfe_list(ctx);
298 frr_each(nhlfe_list_const, head, nhlfe) {
299 nexthop = nhlfe->nexthop;
300 if (!nexthop)
301 continue;
302
303 if (nexthop_num >= zrouter.multipath_num)
304 break;
305
306 if (((action == RTM_ADD || action == RTM_CHANGE)
307 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
308 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)))
309 || (action == RTM_DELETE
310 && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
311 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) {
312 if (nhlfe->nexthop->nh_label->num_labels > 1) {
313 flog_warn(EC_ZEBRA_MAX_LABELS_PUSH,
314 "%s: can't push %u labels at once (maximum is 1)",
315 __func__,
316 nhlfe->nexthop->nh_label->num_labels);
317 continue;
318 }
319
320 nexthop_num++;
321
322 switch (NHLFE_FAMILY(nhlfe)) {
323 case AF_INET:
324 kernel_send_rtmsg_v4(
325 action,
326 dplane_ctx_get_in_label(ctx),
327 nhlfe);
328 break;
329 case AF_INET6:
330 kernel_send_rtmsg_v6(
331 action,
332 dplane_ctx_get_in_label(ctx),
333 nhlfe);
334 break;
335 default:
336 break;
337 }
338 }
339 }
340
341 return 0;
342 }
343
344 enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
345 {
346 int ret;
347
348 ret = kernel_lsp_cmd(ctx);
349
350 return (ret == 0 ?
351 ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
352 }
353
354 static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
355 {
356 struct ifreq ifr;
357 struct ifmpwreq imr;
358 struct sockaddr_storage ss;
359 struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss;
360 struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss;
361 const union g_addr *gaddr;
362
363 memset(&imr, 0, sizeof(imr));
364 switch (dplane_ctx_get_pw_type(ctx)) {
365 case PW_TYPE_ETHERNET:
366 imr.imr_type = IMR_TYPE_ETHERNET;
367 break;
368 case PW_TYPE_ETHERNET_TAGGED:
369 imr.imr_type = IMR_TYPE_ETHERNET_TAGGED;
370 break;
371 default:
372 zlog_debug("%s: unhandled pseudowire type (%#X)", __func__,
373 dplane_ctx_get_pw_type(ctx));
374 return ZEBRA_DPLANE_REQUEST_FAILURE;
375 }
376
377 if (dplane_ctx_get_pw_flags(ctx) & F_PSEUDOWIRE_CWORD)
378 imr.imr_flags |= IMR_FLAG_CONTROLWORD;
379
380 /* pseudowire nexthop */
381 memset(&ss, 0, sizeof(ss));
382 gaddr = dplane_ctx_get_pw_dest(ctx);
383 switch (dplane_ctx_get_pw_af(ctx)) {
384 case AF_INET:
385 sa_in->sin_family = AF_INET;
386 sa_in->sin_len = sizeof(struct sockaddr_in);
387 sa_in->sin_addr = gaddr->ipv4;
388 break;
389 case AF_INET6:
390 sa_in6->sin6_family = AF_INET6;
391 sa_in6->sin6_len = sizeof(struct sockaddr_in6);
392 sa_in6->sin6_addr = gaddr->ipv6;
393 break;
394 default:
395 zlog_debug("%s: unhandled pseudowire address-family (%u)",
396 __func__, dplane_ctx_get_pw_af(ctx));
397 return ZEBRA_DPLANE_REQUEST_FAILURE;
398 }
399 memcpy(&imr.imr_nexthop, (struct sockaddr *)&ss,
400 sizeof(imr.imr_nexthop));
401
402 /* pseudowire local/remote labels */
403 imr.imr_lshim.shim_label = dplane_ctx_get_pw_local_label(ctx);
404 imr.imr_rshim.shim_label = dplane_ctx_get_pw_remote_label(ctx);
405
406 /* ioctl */
407 memset(&ifr, 0, sizeof(ifr));
408 strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx),
409 sizeof(ifr.ifr_name));
410 ifr.ifr_data = (caddr_t)&imr;
411 if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
412 flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s",
413 safe_strerror(errno));
414 return ZEBRA_DPLANE_REQUEST_FAILURE;
415 }
416
417 return ZEBRA_DPLANE_REQUEST_SUCCESS;
418 }
419
420 static enum zebra_dplane_result kmpw_uninstall(struct zebra_dplane_ctx *ctx)
421 {
422 struct ifreq ifr;
423 struct ifmpwreq imr;
424
425 memset(&ifr, 0, sizeof(ifr));
426 memset(&imr, 0, sizeof(imr));
427 strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx),
428 sizeof(ifr.ifr_name));
429 ifr.ifr_data = (caddr_t)&imr;
430 if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
431 flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s",
432 safe_strerror(errno));
433 return ZEBRA_DPLANE_REQUEST_FAILURE;
434 }
435
436 return ZEBRA_DPLANE_REQUEST_SUCCESS;
437 }
438
439 /*
440 * Pseudowire update api for openbsd.
441 */
442 enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
443 {
444 enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
445
446 switch (dplane_ctx_get_op(ctx)) {
447 case DPLANE_OP_PW_INSTALL:
448 result = kmpw_install(ctx);
449 break;
450 case DPLANE_OP_PW_UNINSTALL:
451 result = kmpw_uninstall(ctx);
452 break;
453 case DPLANE_OP_NONE:
454 case DPLANE_OP_ROUTE_INSTALL:
455 case DPLANE_OP_ROUTE_UPDATE:
456 case DPLANE_OP_ROUTE_DELETE:
457 case DPLANE_OP_ROUTE_NOTIFY:
458 case DPLANE_OP_NH_INSTALL:
459 case DPLANE_OP_NH_UPDATE:
460 case DPLANE_OP_NH_DELETE:
461 case DPLANE_OP_LSP_INSTALL:
462 case DPLANE_OP_LSP_UPDATE:
463 case DPLANE_OP_LSP_DELETE:
464 case DPLANE_OP_LSP_NOTIFY:
465 case DPLANE_OP_SYS_ROUTE_ADD:
466 case DPLANE_OP_SYS_ROUTE_DELETE:
467 case DPLANE_OP_ADDR_INSTALL:
468 case DPLANE_OP_ADDR_UNINSTALL:
469 case DPLANE_OP_MAC_INSTALL:
470 case DPLANE_OP_MAC_DELETE:
471 case DPLANE_OP_NEIGH_INSTALL:
472 case DPLANE_OP_NEIGH_UPDATE:
473 case DPLANE_OP_NEIGH_DELETE:
474 case DPLANE_OP_VTEP_ADD:
475 case DPLANE_OP_VTEP_DELETE:
476 case DPLANE_OP_RULE_ADD:
477 case DPLANE_OP_RULE_DELETE:
478 case DPLANE_OP_RULE_UPDATE:
479 case DPLANE_OP_NEIGH_DISCOVER:
480 case DPLANE_OP_BR_PORT_UPDATE:
481 case DPLANE_OP_IPTABLE_ADD:
482 case DPLANE_OP_IPTABLE_DELETE:
483 case DPLANE_OP_IPSET_ADD:
484 case DPLANE_OP_IPSET_DELETE:
485 case DPLANE_OP_IPSET_ENTRY_ADD:
486 case DPLANE_OP_IPSET_ENTRY_DELETE:
487 case DPLANE_OP_NEIGH_IP_INSTALL:
488 case DPLANE_OP_NEIGH_IP_DELETE:
489 case DPLANE_OP_NEIGH_TABLE_UPDATE:
490 case DPLANE_OP_GRE_SET:
491 case DPLANE_OP_INTF_ADDR_ADD:
492 case DPLANE_OP_INTF_ADDR_DEL:
493 case DPLANE_OP_INTF_NETCONFIG:
494 case DPLANE_OP_INTF_INSTALL:
495 case DPLANE_OP_INTF_UPDATE:
496 case DPLANE_OP_INTF_DELETE:
497 case DPLANE_OP_TC_QDISC_INSTALL:
498 case DPLANE_OP_TC_QDISC_UNINSTALL:
499 case DPLANE_OP_TC_CLASS_ADD:
500 case DPLANE_OP_TC_CLASS_DELETE:
501 case DPLANE_OP_TC_CLASS_UPDATE:
502 case DPLANE_OP_TC_FILTER_ADD:
503 case DPLANE_OP_TC_FILTER_DELETE:
504 case DPLANE_OP_TC_FILTER_UPDATE:
505 break;
506 }
507
508 return result;
509 }
510
511 #define MAX_RTSOCK_BUF 128 * 1024
512 int mpls_kernel_init(void)
513 {
514 int rcvbuf, default_rcvbuf;
515 socklen_t optlen;
516
517 if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
518 flog_err_sys(EC_LIB_SOCKET, "%s: socket", __func__);
519 return -1;
520 }
521
522 if ((kr_state.ioctl_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0))
523 == -1) {
524 flog_err_sys(EC_LIB_SOCKET, "%s: ioctl socket", __func__);
525 return -1;
526 }
527
528 /* grow receive buffer, don't wanna miss messages */
529 optlen = sizeof(default_rcvbuf);
530 if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &default_rcvbuf,
531 &optlen)
532 == -1)
533 flog_err_sys(EC_LIB_SOCKET,
534 "kr_init getsockopt SOL_SOCKET SO_RCVBUF");
535 else
536 for (rcvbuf = MAX_RTSOCK_BUF;
537 rcvbuf > default_rcvbuf
538 && setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf,
539 sizeof(rcvbuf))
540 == -1
541 && errno == ENOBUFS;
542 rcvbuf /= 2)
543 ; /* nothing */
544
545 kr_state.rtseq = 1;
546
547 /* Strict pseudowire reachability checking required for obsd */
548 mpls_pw_reach_strict = true;
549
550 return 0;
551 }
552
553 #endif /* OPEN_BSD */