• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Based on net/ipv4/udp.c
4  * Authors:	Ross Biro
5  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
6  *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
7  *		Alan Cox, <alan@lxorguk.ukuu.org.uk>
8  *		Hirokazu Takahashi, <taka@valinux.co.jp>
9  *
10  * Fixes:
11  *		Alan Cox	:	verify_area() calls
12  *		Alan Cox	:	stopped close while in use off icmp
13  *					messages. Not a fix but a botch that
14  *					for udp at least is 'valid'.
15  *		Alan Cox	:	Fixed icmp handling properly
16  *		Alan Cox	:	Correct error for oversized datagrams
17  *		Alan Cox	:	Tidied select() semantics.
18  *		Alan Cox	:	udp_err() fixed properly, also now
19  *					select and read wake correctly on errors
20  *		Alan Cox	:	udp_send verify_area moved to avoid mem leak
21  *		Alan Cox	:	UDP can count its memory
22  *		Alan Cox	:	send to an unknown connection causes
23  *					an ECONNREFUSED off the icmp, but
24  *					does NOT close.
25  *		Alan Cox	:	Switched to new sk_buff handlers. No more backlog!
26  *		Alan Cox	:	Using generic datagram code. Even smaller and the PEEK
27  *					bug no longer crashes it.
28  *		Fred Van Kempen	:	Net2e support for sk->broadcast.
29  *		Alan Cox	:	Uses skb_free_datagram
30  *		Alan Cox	:	Added get/set sockopt support.
31  *		Alan Cox	:	Broadcasting without option set returns EACCES.
32  *		Alan Cox	:	No wakeup calls. Instead we now use the callbacks.
33  *		Alan Cox	:	Use ip_tos and ip_ttl
34  *		Alan Cox	:	SNMP Mibs
35  *		Alan Cox	:	MSG_DONTROUTE, and 0.0.0.0 support.
36  *		Matt Dillon	:	UDP length checks.
37  *		Alan Cox	:	Smarter af_inet used properly.
38  *		Alan Cox	:	Use new kernel side addressing.
39  *		Alan Cox	:	Incorrect return on truncated datagram receive.
40  *	Arnt Gulbrandsen	:	New udp_send and stuff
41  *		Alan Cox	:	Cache last socket
42  *		Alan Cox	:	Route cache
43  *		Jon Peatfield	:	Minor efficiency fix to sendto().
44  *		Mike Shaver	:	RFC1122 checks.
45  *		Alan Cox	:	Nonblocking error fix.
46  *	Willy Konynenberg	:	Transparent proxying support.
47  *		Mike McLagan	:	Routing by source
48  *		David S. Miller	:	New socket lookup architecture.
49  *					Last socket cache retained as it
50  *					does have a high hit rate.
51  *		Olaf Kirch	:	Don't linearise iovec on sendmsg.
52  *		Andi Kleen	:	Some cleanups, cache destination entry
53  *					for connect.
54  *	Vitaly E. Lavrov	:	Transparent proxy revived after year coma.
55  *		Melvin Smith	:	Check msg_name not msg_namelen in sendto(),
56  *					return ENOTCONN for unconnected sockets (POSIX)
57  *		Janos Farkas	:	don't deliver multi/broadcasts to a different
58  *					bound-to-device socket
59  *	Hirokazu Takahashi	:	HW checksumming for outgoing UDP
60  *					datagrams.
61  *	Hirokazu Takahashi	:	sendfile() on UDP works now.
62  *		Arnaldo C. Melo :	convert /proc/net/udp to seq_file
63  *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
64  *	Alexey Kuznetsov:		allow both IPv4 and IPv6 sockets to bind
65  *					a single port at the same time.
66  *	Derek Atkins <derek@ihtfp.com>: Add Encapulation Support
67  *	James Chapman		:	Add L2TP encapsulation type.
68  *
69  * Based on net/ipv6/udp.c
70  *	Authors:
71  *	Pedro Roque		<roque@di.fc.ul.pt>
72  *
73  *	Fixes:
74  *	Hideaki YOSHIFUJI	:	sin6_scope_id support
75  *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
76  *	Alexey Kuznetsov		allow both IPv4 and IPv6 sockets to bind
77  *					a single port at the same time.
78  *      Kazunori MIYAZAWA @USAGI:       change process style to use ip6_append_data
79  *      YOSHIFUJI Hideaki @USAGI:	convert /proc/net/udp6 to seq_file.
80  *
81  * NewIP INET
82  * An implementation of the TCP/IP protocol suite for the LINUX
83  * operating system. NewIP INET is implemented using the  BSD Socket
84  * interface as the means of communication with the user level.
85  *
86  * The User Datagram Protocol (NewIP UDP).
87  */
88 #define pr_fmt(fmt) KBUILD_MODNAME ": [%s:%d] " fmt, __func__, __LINE__
89 
90 #include <linux/uaccess.h>
91 #include <linux/errno.h>
92 #include <linux/if_arp.h>
93 #include <linux/init.h>
94 #include <linux/module.h>
95 #include <linux/net.h>
96 #include <linux/netdevice.h>
97 #include <linux/nip.h>
98 #include <linux/skbuff.h>
99 #include <linux/socket.h>
100 #include <linux/types.h>
101 
102 #include <net/addrconf.h>
103 #include <net/busy_poll.h>
104 #include <net/nip.h>
105 #include <net/nip_udp.h>
106 #include <net/nip_fib.h>
107 #include <net/nip_addrconf.h>
108 #include <net/protocol.h>
109 #include <net/raw.h>
110 #include <net/sock_reuseport.h>
111 #include <net/udp.h>
112 #include "nip_hdr.h"
113 #include "nip_checksum.h"
114 #include "tcp_nip_parameter.h"
115 
nip_udp_portaddr_hash(const struct net * net,const struct nip_addr * niaddr,u_short port)116 static u32 nip_udp_portaddr_hash(const struct net *net,
117 				 const struct nip_addr *niaddr,
118 				 u_short port)
119 {
120 	u32 hash;
121 	u32 mix = net_hash_mix(net);
122 
123 	/* use nip_addr_hash() to obtain a hash result of nip_addr */
124 	hash = jhash_1word(nip_addr_hash(niaddr), mix);
125 
126 	return hash ^ port;
127 }
128 
129 /* Called during the bind & sendto procedure, bind ports */
nip_udp_get_port(struct sock * sk,unsigned short snum)130 int nip_udp_get_port(struct sock *sk, unsigned short snum)
131 {
132 	unsigned int hash2_nulladdr, hash2_partial;
133 
134 	hash2_nulladdr = nip_udp_portaddr_hash(sock_net(sk), &nip_any_addr, snum);
135 	/* hash2_partial is the hash result of nip_addr only */
136 	hash2_partial = nip_udp_portaddr_hash(sock_net(sk), &sk->SK_NIP_RCV_SADDR, 0);
137 
138 	/* precompute partial secondary hash */
139 	udp_sk(sk)->udp_portaddr_hash = hash2_partial;
140 	return udp_lib_get_port(sk, snum, hash2_nulladdr);
141 }
142 
nip_udp_compute_score(struct sock * sk,struct net * net,const struct nip_addr * saddr,__be16 sport,const struct nip_addr * daddr,unsigned short hnum,int dif,int sdif)143 static int nip_udp_compute_score(struct sock *sk, struct net *net,
144 				 const struct nip_addr *saddr, __be16 sport,
145 				 const struct nip_addr *daddr, unsigned short hnum,
146 				 int dif, int sdif)
147 {
148 	int score = 0;
149 	struct inet_sock *inet;
150 
151 	if (!net_eq(sock_net(sk), net) ||
152 	    udp_sk(sk)->udp_port_hash != hnum ||
153 	    sk->sk_family != PF_NINET)
154 		return -1;
155 
156 	/* Destination port of the peer device
157 	 * In the header sent by the peer end, it is the source port
158 	 */
159 	inet = inet_sk(sk);
160 	if (inet->inet_dport) {
161 		if (inet->inet_dport != sport)
162 			return -1;
163 		score++;
164 	}
165 
166 	/* Source ADDRESS of the local device
167 	 * In the header sent by the peer device, it is the destination address
168 	 */
169 	if (!nip_addr_any(&sk->SK_NIP_RCV_SADDR)) {
170 		if (!nip_addr_eq(&sk->SK_NIP_RCV_SADDR, daddr))
171 			return -1;
172 		score++;
173 	}
174 
175 	/* Address of the peer device
176 	 * In the packet header sent by the peer device, is the source ADDRESS
177 	 */
178 	if (!nip_addr_any(&sk->SK_NIP_DADDR)) {
179 		if (!nip_addr_eq(&sk->SK_NIP_DADDR, saddr))
180 			return -1;
181 		score++;
182 	}
183 
184 	/* Check the dev index */
185 	if (sk->sk_bound_dev_if) {
186 		bool dev_match = dif == sk->sk_bound_dev_if || sdif == sk->sk_bound_dev_if;
187 
188 		if (!dev_match)
189 			return -1;
190 		score++;
191 	}
192 
193 	if (sk->sk_incoming_cpu == raw_smp_processor_id())
194 		score++;
195 	return score;
196 }
197 
nip_udp_lib_lookup2(struct net * net,const struct nip_addr * saddr,u_short sport,const struct nip_addr * daddr,unsigned short hnum,int dif,int sdif,struct udp_hslot * hslot2,struct sk_buff * skb)198 static struct sock *nip_udp_lib_lookup2(struct net *net,
199 					const struct nip_addr *saddr,
200 					u_short sport,
201 					const struct nip_addr *daddr,
202 					unsigned short hnum,
203 					int dif, int sdif,
204 					struct udp_hslot *hslot2,
205 					struct sk_buff *skb)
206 {
207 	struct sock *sk;
208 	struct sock *result = NULL;
209 	int badness = -1;
210 
211 	udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
212 		int score = nip_udp_compute_score(sk, net, saddr, sport, daddr, hnum, dif, sdif);
213 
214 		if (score > badness) {
215 			result = sk;
216 			badness = score;
217 		}
218 	}
219 	return result;
220 }
221 
222 /* rcu_read_lock() must be held */
__nip_udp_lib_lookup(struct net * net,const struct nip_addr * saddr,__be16 sport,const struct nip_addr * daddr,__be16 dport,int dif,int sdif,struct udp_table * udptable,struct sk_buff * skb)223 struct sock *__nip_udp_lib_lookup(struct net *net,
224 				  const struct nip_addr *saddr, __be16 sport,
225 				  const struct nip_addr *daddr, __be16 dport,
226 				  int dif, int sdif, struct udp_table *udptable,
227 				  struct sk_buff *skb)
228 {
229 	unsigned short hnum = ntohs(dport);
230 	unsigned int hash2, slot2;
231 	struct udp_hslot *hslot2;
232 	struct sock *result;
233 
234 	/* mask ensures that the hash index is valid without memory overruns */
235 	hash2 = nip_udp_portaddr_hash(net, daddr, hnum);
236 	slot2 = hash2 & udptable->mask;
237 	hslot2 = &udptable->hash2[slot2];
238 
239 	/* Lookup connected or non-wildcard sockets */
240 	result = nip_udp_lib_lookup2(net, saddr, sport,
241 				     daddr, hnum, dif, sdif,
242 				     hslot2, skb);
243 	if (!IS_ERR_OR_NULL(result))
244 		goto done;
245 
246 	/* Lookup wildcard sockets */
247 	/* mask ensures that the hash index is valid without memory overruns */
248 	hash2 = nip_udp_portaddr_hash(net, &nip_any_addr, hnum);
249 	slot2 = hash2 & udptable->mask;
250 	hslot2 = &udptable->hash2[slot2];
251 
252 	result = nip_udp_lib_lookup2(net, saddr, sport,
253 				     &nip_any_addr, hnum, dif, sdif,
254 				     hslot2, skb);
255 done:
256 	if (IS_ERR(result))
257 		return NULL;
258 	return result;
259 }
260 
__nip_udp_lib_lookup_skb(struct sk_buff * skb,__be16 sport,__be16 dport,struct udp_table * udptable)261 static struct sock *__nip_udp_lib_lookup_skb(struct sk_buff *skb,
262 					     __be16 sport, __be16 dport,
263 					     struct udp_table *udptable)
264 {
265 	return __nip_udp_lib_lookup(dev_net(skb->dev),
266 				&nipcb(skb)->srcaddr, sport,
267 				&nipcb(skb)->dstaddr, dport, skb->skb_iif,
268 				0, udptable, skb);
269 }
270 
udp_table_del(struct sock * sk)271 void udp_table_del(struct sock *sk)
272 {
273 	udp_lib_unhash(sk);
274 }
275 
nip_udp_recvmsg(struct sock * sk,struct msghdr * msg,size_t len,int noblock,int flags,int * addr_len)276 int nip_udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
277 		    int noblock, int flags, int *addr_len)
278 {
279 	struct sk_buff *skb;
280 	unsigned int ulen, copied;
281 	int peeking, off, datalen;
282 	int err;
283 
284 	off = sk_peek_offset(sk, flags);
285 	peeking = off; /* Fetch the SKB from the queue */
286 	skb = __skb_recv_udp(sk, flags, noblock, &off, &err);
287 	if (!skb)
288 		return err;
289 	ulen = skb->len;
290 	copied = len;
291 	if (copied > ulen - off)
292 		copied = ulen - off;
293 	else if (copied < ulen)
294 		msg->msg_flags |= MSG_TRUNC;
295 
296 	/* copy data */
297 	datalen = copy_to_iter(skb->data, copied, &msg->msg_iter);
298 	if (datalen < 0) {
299 		nip_dbg("copy to iter in failure, len=%d", datalen);
300 		err = -EFAULT;
301 		return err;
302 	}
303 
304 	sock_recv_ts_and_drops(msg, sk, skb);
305 	/* Update information such as the timestamp received
306 	 * by the last datagram in the transport control block
307 	 */
308 	/* copy the address */
309 	if (msg->msg_name) {
310 		DECLARE_SOCKADDR(struct sockaddr_nin *, sin, msg->msg_name);
311 
312 		sin->sin_family = AF_NINET;
313 		sin->sin_port = udp_hdr(skb)->source;
314 		sin->sin_addr = nipcb(skb)->srcaddr;
315 		*addr_len = sizeof(*sin);
316 	}
317 
318 	err = copied;
319 	if (flags & MSG_TRUNC)
320 		err = ulen;
321 
322 	skb_consume_udp(sk, skb, peeking ? -err : err);
323 	return err;
324 }
325 
nip_udp_err(struct sk_buff * skb,struct ninet_skb_parm * opt,u8 type,u8 code,int offset,__be32 info)326 static void nip_udp_err(struct sk_buff *skb,
327 			struct ninet_skb_parm *opt,
328 			u8 type,
329 			u8 code, int offset,
330 			__be32 info)
331 {
332 }
333 
__nip_udp_queue_rcv_skb(struct sock * sk,struct sk_buff * skb)334 static int __nip_udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
335 {
336 	int rc;
337 
338 	sk_incoming_cpu_update(sk);
339 
340 	rc = __udp_enqueue_schedule_skb(sk, skb);
341 	if (rc < 0) {
342 		kfree_skb(skb);
343 		return -1;
344 	}
345 	return 0;
346 }
347 
nip_get_udp_input_checksum(struct sk_buff * skb)348 bool nip_get_udp_input_checksum(struct sk_buff *skb)
349 {
350 	struct nip_pseudo_header nph = {0};
351 	struct udphdr *udphead = udp_hdr(skb);
352 	unsigned short check_len = ntohs(udphead->len);
353 
354 	nph.nexthdr = nipcb(skb)->nexthdr;
355 	nph.saddr = nipcb(skb)->srcaddr;
356 	nph.daddr = nipcb(skb)->dstaddr;
357 	nph.check_len = udphead->len;
358 
359 	return nip_check_sum_parse(skb_transport_header(skb), check_len, &nph)
360 	       == 0xffff ? true : false;
361 }
362 
363 /* Udp packets are received at the network layer */
nip_udp_input(struct sk_buff * skb)364 int nip_udp_input(struct sk_buff *skb)
365 {
366 	struct sock *sk;
367 	int rc = -EINVAL;
368 	struct udphdr *udphead;
369 
370 	if (!pskb_may_pull(skb, sizeof(struct udphdr))) {
371 		nip_dbg("invalid skb length, drop the packet(skb->len=%u)", skb->len);
372 		kfree_skb(skb);
373 		goto end;
374 	}
375 
376 	udphead = udp_hdr(skb);
377 	if (ntohs(udphead->len) < sizeof(struct udphdr) ||
378 	    ntohs(udphead->len) > skb->len) {
379 		nip_dbg("invalid udp packet length, drop the packet(udphead->len=%u)",
380 			ntohs(udphead->len));
381 		kfree_skb(skb);
382 		goto end;
383 	}
384 
385 	if (!nip_get_udp_input_checksum(skb)) {
386 		nip_dbg("checksum failed, drop the packet");
387 		kfree_skb(skb);
388 		goto end;
389 	}
390 
391 	sk = __nip_udp_lib_lookup_skb(skb, udphead->source,
392 				      udphead->dest, &udp_table);
393 	if (!sk) {
394 		nip_dbg("dport not match, drop the packet. sport=%u, dport=%u, data_len=%u",
395 			ntohs(udphead->source), ntohs(udphead->dest), ntohs(udphead->len));
396 		kfree_skb(skb);
397 		goto end;
398 	}
399 
400 	skb_pull(skb, sizeof(struct udphdr));
401 	skb->len = ntohs(udphead->len) - sizeof(struct udphdr);
402 
403 	skb_dst_drop(skb);
404 	/* enqueue */
405 	rc = __nip_udp_queue_rcv_skb(sk, skb);
406 end:
407 	return rc;
408 }
409 
nip_udp_output(struct sock * sk,struct msghdr * msg,size_t len)410 int nip_udp_output(struct sock *sk, struct msghdr *msg, size_t len)
411 {
412 	DECLARE_SOCKADDR(struct sockaddr_nin *, sin, msg->msg_name);
413 	struct flow_nip fln;
414 	u_short sport, dport;
415 	struct dst_entry *dst;
416 	int err;
417 	struct inet_sock *inet;
418 
419 	if (!sin)
420 		/* Currently, udp socket Connect function is not implemented.
421 		 * The destination address and port must be directly provided by Sendto
422 		 */
423 		return -EDESTADDRREQ;
424 
425 	if (sin->sin_family != AF_NINET) {
426 		nip_dbg("sin_family false");
427 		return -EAFNOSUPPORT;
428 	}
429 	if (nip_addr_invalid(&sin->sin_addr)) {
430 		nip_dbg("sin_addr false");
431 		return -EFAULT;
432 	}
433 	if (is_nip_local_addr(&sin->sin_addr)) {
434 		err = ninet_ioctl_cmd(sk->sk_socket, msg->msg_iter.iov);
435 		if (!err) {
436 			nip_dbg("ninet_ioctl_cmd succeed");
437 			return err;
438 		} else if (err != -NIP_IOCTL_FLAG_INVALID) {
439 			nip_dbg("ninet_ioctl_cmd failed");
440 			return err;
441 		}
442 	}
443 
444 	inet = inet_sk(sk);
445 	/* Destination address, port (network order) must be specified when sendto */
446 	dport = sin->sin_port;
447 	fln.daddr = sin->sin_addr;
448 	sport = htons(inet->inet_num);
449 
450 	/* Check the dev index */
451 	fln.FLOWIN_OIF = sk->sk_bound_dev_if;
452 
453 	/* Query the route & Obtain the Saddr */
454 	dst = nip_sk_dst_lookup_flow(sk, &fln);
455 	if (IS_ERR(dst)) {
456 		err = PTR_ERR(dst);
457 		dst = NULL;
458 		goto out;
459 	}
460 
461 	err = _nip_udp_output(sk, msg, len,
462 			      sizeof(struct udphdr), &fln.saddr,
463 			      sport, &fln.daddr,
464 			      dport, dst);
465 
466 out:
467 	dst_release(dst);
468 	if (!err)
469 		return len;
470 
471 	return err;
472 }
473 
474 /* Close the connection using */
nip_udp_destroy_sock(struct sock * sk)475 void nip_udp_destroy_sock(struct sock *sk)
476 {
477 	udp_table_del(sk);
478 	ninet_destroy_sock(sk);
479 }
480 
481 /* socket option code for udp */
nip_udp_setsockopt(struct sock * sk,int level,int optname,sockptr_t optval,unsigned int optlen)482 int nip_udp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
483 		       unsigned int optlen)
484 {
485 	if (level == SOL_UDP || level == SOL_UDPLITE)
486 		return 0;
487 	return nip_setsockopt(sk, level, optname, optval, optlen);
488 }
489 
nip_udp_getsockopt(struct sock * sk,int level,int optname,char __user * optval,int __user * optlen)490 int nip_udp_getsockopt(struct sock *sk, int level,
491 		       int optname, char __user *optval,
492 		       int __user *optlen)
493 {
494 	if (level == SOL_UDP || level == SOL_UDPLITE)
495 		return 0;
496 	return nip_getsockopt(sk, level, optname, optval, optlen);
497 }
498 
nip_udp_datagram_connect(struct sock * sk,struct sockaddr * uaddr,int addr_len)499 int nip_udp_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
500 {
501 	return -EINVAL;
502 }
503 
nip_udp_pre_connect(struct sock * sk,struct sockaddr * uaddr,int addr_len)504 int nip_udp_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
505 {
506 	return -EINVAL;
507 }
508 
nip_udp_sendpage(struct sock * sk,struct page * page,int offset,size_t size,int flags)509 int nip_udp_sendpage(struct sock *sk, struct page *page, int offset,
510 		     size_t size, int flags)
511 {
512 	return -EINVAL;
513 }
514 
nip_udp_datagram_release_cb(struct sock * sk)515 void nip_udp_datagram_release_cb(struct sock *sk)
516 {
517 }
518 
udp_nip_rehash(struct sock * sk)519 void udp_nip_rehash(struct sock *sk)
520 {
521 }
522 
nip_udp_early_demux(struct sk_buff * skb)523 void nip_udp_early_demux(struct sk_buff *skb)
524 {
525 }
526 
527 static const struct ninet_protocol nip_udp_protocol = {
528 	.handler	= nip_udp_input,
529 	.err_handler	= nip_udp_err,
530 	.early_demux	= nip_udp_early_demux,
531 	.flags		= 0,
532 };
533 
534 /* Newip Udp related operations */
535 struct proto nip_udp_prot = {
536 	.name			= "nip_udp",
537 	.owner			= THIS_MODULE,
538 	.close			= udp_lib_close,
539 	.pre_connect		= nip_udp_pre_connect,
540 	.connect		= nip_udp_datagram_connect,
541 	.disconnect		= udp_disconnect,
542 	.ioctl			= udp_ioctl,
543 	.init			= udp_init_sock,
544 	.destroy		= nip_udp_destroy_sock,
545 	.setsockopt		= nip_udp_setsockopt,
546 	.getsockopt		= nip_udp_getsockopt,
547 	.sendmsg		= nip_udp_output,
548 	.recvmsg		= nip_udp_recvmsg,
549 	.sendpage		= nip_udp_sendpage,
550 	.release_cb		= nip_udp_datagram_release_cb,
551 	.backlog_rcv		= __nip_udp_queue_rcv_skb,
552 	.hash			= udp_lib_hash,
553 	.unhash			= udp_lib_unhash,
554 	.rehash			= udp_nip_rehash,
555 	.get_port		= nip_udp_get_port,
556 	.memory_allocated	= &udp_memory_allocated,
557 	.sysctl_mem		= sysctl_udp_mem,
558 	.obj_size		= sizeof(struct nip_udp_sock),
559 	.h.udp_table		= &udp_table,
560 	.diag_destroy		= udp_abort,
561 };
562 
563 /* Example Create newip socket information */
564 static struct inet_protosw nip_udp_protosw = {
565 	.type = SOCK_DGRAM,
566 	.protocol = IPPROTO_UDP,
567 	.prot = &nip_udp_prot,
568 	.ops = &ninet_dgram_ops,
569 	.flags = INET_PROTOSW_PERMANENT,
570 };
571 
572 /* Af_NINET initializes the call */
nip_udp_init(void)573 int __init nip_udp_init(void)
574 {
575 	int ret;
576 
577 	ret = ninet_add_protocol(&nip_udp_protocol, IPPROTO_UDP);
578 	if (ret)
579 		goto out;
580 
581 	ret = ninet_register_protosw(&nip_udp_protosw);
582 	if (ret)
583 		goto out_nip_udp_protocol;
584 out:
585 	return ret;
586 
587 out_nip_udp_protocol:
588 	ninet_del_protocol(&nip_udp_protocol, IPPROTO_UDP);
589 	goto out;
590 }
591 
nip_udp_exit(void)592 void nip_udp_exit(void)
593 {
594 	ninet_unregister_protosw(&nip_udp_protosw);
595 	ninet_del_protocol(&nip_udp_protocol, IPPROTO_UDP);
596 }
597