]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* |
2 | * OSPF network related functions | |
3 | * Copyright (C) 1999 Toshiaki Takada | |
4 | * | |
5 | * This file is part of GNU Zebra. | |
6 | * | |
7 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2, or (at your option) any | |
10 | * later version. | |
11 | * | |
12 | * GNU Zebra is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
19 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
20 | * 02111-1307, USA. | |
21 | */ | |
22 | ||
23 | #include <zebra.h> | |
24 | ||
25 | #include "thread.h" | |
26 | #include "linklist.h" | |
27 | #include "prefix.h" | |
28 | #include "if.h" | |
29 | #include "sockunion.h" | |
30 | #include "log.h" | |
31 | #include "sockopt.h" | |
edd7c245 | 32 | #include "privs.h" |
33 | ||
34 | extern struct zebra_privs_t ospfd_privs; | |
718e3744 | 35 | |
36 | #include "ospfd/ospfd.h" | |
37 | #include "ospfd/ospf_network.h" | |
38 | #include "ospfd/ospf_interface.h" | |
39 | #include "ospfd/ospf_asbr.h" | |
40 | #include "ospfd/ospf_lsa.h" | |
41 | #include "ospfd/ospf_lsdb.h" | |
42 | #include "ospfd/ospf_neighbor.h" | |
43 | #include "ospfd/ospf_packet.h" | |
44 | ||
edd7c245 | 45 | |
46 | ||
718e3744 | 47 | /* Join to the OSPF ALL SPF ROUTERS multicast group. */ |
48 | int | |
49 | ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, | |
b892f1dd | 50 | ifindex_t ifindex) |
718e3744 | 51 | { |
52 | int ret; | |
53 | ||
69bf3a39 | 54 | ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, |
4a3867d0 | 55 | p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), |
718e3744 | 56 | ifindex); |
57 | if (ret < 0) | |
3dc56b5b | 58 | zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " |
59 | "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " | |
60 | "on # of multicast group memberships has been exceeded?", | |
61 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 62 | else |
ec70497b | 63 | zlog_debug ("interface %s [%u] join AllSPFRouters Multicast group.", |
42c98199 | 64 | inet_ntoa (p->u.prefix4), ifindex); |
718e3744 | 65 | |
66 | return ret; | |
67 | } | |
68 | ||
69 | int | |
70 | ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p, | |
b892f1dd | 71 | ifindex_t ifindex) |
718e3744 | 72 | { |
73 | int ret; | |
74 | ||
69bf3a39 | 75 | ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, |
4a3867d0 | 76 | p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), |
718e3744 | 77 | ifindex); |
78 | if (ret < 0) | |
3dc56b5b | 79 | zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " |
80 | "ifindex %u, AllSPFRouters): %s", | |
81 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 82 | else |
ec70497b PJ |
83 | zlog_debug ("interface %s [%u] leave AllSPFRouters Multicast group.", |
84 | inet_ntoa (p->u.prefix4), ifindex); | |
718e3744 | 85 | |
86 | return ret; | |
87 | } | |
88 | ||
89 | /* Join to the OSPF ALL Designated ROUTERS multicast group. */ | |
90 | int | |
b892f1dd | 91 | ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) |
718e3744 | 92 | { |
93 | int ret; | |
94 | ||
69bf3a39 | 95 | ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, |
4a3867d0 | 96 | p->u.prefix4, htonl (OSPF_ALLDROUTERS), |
718e3744 | 97 | ifindex); |
98 | if (ret < 0) | |
3dc56b5b | 99 | zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " |
100 | "ifindex %u, AllDRouters): %s; perhaps a kernel limit " | |
101 | "on # of multicast group memberships has been exceeded?", | |
102 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 103 | else |
ec70497b PJ |
104 | zlog_debug ("interface %s [%u] join AllDRouters Multicast group.", |
105 | inet_ntoa (p->u.prefix4), ifindex); | |
718e3744 | 106 | |
107 | return ret; | |
108 | } | |
109 | ||
110 | int | |
b892f1dd | 111 | ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) |
718e3744 | 112 | { |
113 | int ret; | |
114 | ||
69bf3a39 | 115 | ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, |
4a3867d0 | 116 | p->u.prefix4, htonl (OSPF_ALLDROUTERS), |
718e3744 | 117 | ifindex); |
118 | if (ret < 0) | |
3dc56b5b | 119 | zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " |
120 | "ifindex %u, AllDRouters): %s", | |
121 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 122 | else |
ec70497b PJ |
123 | zlog_debug ("interface %s [%u] leave AllDRouters Multicast group.", |
124 | inet_ntoa (p->u.prefix4), ifindex); | |
718e3744 | 125 | |
126 | return ret; | |
127 | } | |
128 | ||
129 | int | |
b892f1dd | 130 | ospf_if_ipmulticast (struct ospf *top, struct prefix *p, ifindex_t ifindex) |
718e3744 | 131 | { |
132 | u_char val; | |
133 | int ret, len; | |
c5bdb09f | 134 | |
718e3744 | 135 | /* Prevent receiving self-origined multicast packets. */ |
c5bdb09f | 136 | ret = setsockopt_ipv4_multicast_loop (top->fd, 0); |
718e3744 | 137 | if (ret < 0) |
3dc56b5b | 138 | zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s", |
139 | top->fd, safe_strerror(errno)); | |
718e3744 | 140 | |
141 | /* Explicitly set multicast ttl to 1 -- endo. */ | |
142 | val = 1; | |
c5bdb09f | 143 | len = sizeof (val); |
718e3744 | 144 | ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len); |
145 | if (ret < 0) | |
3dc56b5b | 146 | zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", |
147 | top->fd, safe_strerror (errno)); | |
718e3744 | 148 | |
4a3867d0 | 149 | ret = setsockopt_ipv4_multicast_if (top->fd, p->u.prefix4, ifindex); |
718e3744 | 150 | if (ret < 0) |
3dc56b5b | 151 | zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, " |
152 | "ifindex %u): %s", | |
153 | top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); | |
718e3744 | 154 | |
155 | return ret; | |
156 | } | |
157 | ||
158 | int | |
159 | ospf_sock_init (void) | |
160 | { | |
161 | int ospf_sock; | |
1423c809 | 162 | int ret, hincl = 1; |
a78d75b0 | 163 | int bufsize = (8 * 1024 * 1024); |
718e3744 | 164 | |
edd7c245 | 165 | if ( ospfd_privs.change (ZPRIVS_RAISE) ) |
166 | zlog_err ("ospf_sock_init: could not raise privs, %s", | |
6099b3b5 | 167 | safe_strerror (errno) ); |
edd7c245 | 168 | |
718e3744 | 169 | ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP); |
170 | if (ospf_sock < 0) | |
171 | { | |
0b7d97d2 | 172 | int save_errno = errno; |
edd7c245 | 173 | if ( ospfd_privs.change (ZPRIVS_LOWER) ) |
174 | zlog_err ("ospf_sock_init: could not lower privs, %s", | |
6099b3b5 | 175 | safe_strerror (errno) ); |
0b7d97d2 | 176 | zlog_err ("ospf_read_sock_init: socket: %s", safe_strerror (save_errno)); |
177 | exit(1); | |
718e3744 | 178 | } |
edd7c245 | 179 | |
5bd4189c | 180 | #ifdef IP_HDRINCL |
181 | /* we will include IP header with packet */ | |
182 | ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl)); | |
183 | if (ret < 0) | |
184 | { | |
0b7d97d2 | 185 | int save_errno = errno; |
5bd4189c | 186 | if ( ospfd_privs.change (ZPRIVS_LOWER) ) |
187 | zlog_err ("ospf_sock_init: could not lower privs, %s", | |
6099b3b5 | 188 | safe_strerror (errno) ); |
0b7d97d2 | 189 | zlog_warn ("Can't set IP_HDRINCL option for fd %d: %s", |
190 | ospf_sock, safe_strerror(save_errno)); | |
5bd4189c | 191 | } |
192 | #elif defined (IPTOS_PREC_INTERNETCONTROL) | |
193 | #warning "IP_HDRINCL not available on this system" | |
194 | #warning "using IPTOS_PREC_INTERNETCONTROL" | |
1423c809 | 195 | ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL); |
718e3744 | 196 | if (ret < 0) |
197 | { | |
0b7d97d2 | 198 | int save_errno = errno; |
edd7c245 | 199 | if ( ospfd_privs.change (ZPRIVS_LOWER) ) |
200 | zlog_err ("ospf_sock_init: could not lower privs, %s", | |
6099b3b5 | 201 | safe_strerror (errno) ); |
0b7d97d2 | 202 | zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s", |
203 | tos, ospf_sock, safe_strerror(save_errno)); | |
718e3744 | 204 | close (ospf_sock); /* Prevent sd leak. */ |
205 | return ret; | |
206 | } | |
5bd4189c | 207 | #else /* !IPTOS_PREC_INTERNETCONTROL */ |
208 | #warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL" | |
209 | zlog_warn ("IP_HDRINCL option not available"); | |
210 | #endif /* IP_HDRINCL */ | |
718e3744 | 211 | |
ac191232 | 212 | ret = setsockopt_ifindex (AF_INET, ospf_sock, 1); |
213 | ||
2dd8bb4e | 214 | if (ret < 0) |
3dc56b5b | 215 | zlog_warn ("Can't set pktinfo option for fd %d", ospf_sock); |
edd7c245 | 216 | |
217 | if (ospfd_privs.change (ZPRIVS_LOWER)) | |
218 | { | |
219 | zlog_err ("ospf_sock_init: could not lower privs, %s", | |
6099b3b5 | 220 | safe_strerror (errno) ); |
edd7c245 | 221 | } |
a78d75b0 | 222 | |
6228a3b8 RW |
223 | setsockopt_so_sendbuf (ospf_sock, bufsize); |
224 | setsockopt_so_recvbuf (ospf_sock, bufsize); | |
a78d75b0 | 225 | |
718e3744 | 226 | return ospf_sock; |
227 | } |