Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *	IEEE 802.1D Generic Attribute Registration Protocol (GARP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *	Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/llc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <net/llc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <net/llc_pdu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <net/garp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) static unsigned int garp_join_time __read_mostly = 200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) module_param(garp_join_time, uint, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) MODULE_PARM_DESC(garp_join_time, "Join time in ms (default 200ms)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) static const struct garp_state_trans {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	u8	state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	u8	action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) } garp_applicant_state_table[GARP_APPLICANT_MAX + 1][GARP_EVENT_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	[GARP_APPLICANT_VA] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_AA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 						    .action = GARP_ACTION_S_JOIN_IN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_AA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_VA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_VA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_LA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	[GARP_APPLICANT_AA] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_QA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 						    .action = GARP_ACTION_S_JOIN_IN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_QA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_VA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_VA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_LA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	[GARP_APPLICANT_QA] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_QA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_VA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_LA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	[GARP_APPLICANT_LA] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_VO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 						    .action = GARP_ACTION_S_LEAVE_EMPTY },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_LA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_LA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_LA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_VA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	[GARP_APPLICANT_VP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_AA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 						    .action = GARP_ACTION_S_JOIN_IN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_AP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	[GARP_APPLICANT_AP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_QA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 						    .action = GARP_ACTION_S_JOIN_IN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_QP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_AO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	[GARP_APPLICANT_QP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_QP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_QO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	[GARP_APPLICANT_VO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_AO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_VP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	[GARP_APPLICANT_AO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_QO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_AP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	[GARP_APPLICANT_QO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		[GARP_EVENT_TRANSMIT_PDU]	= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		[GARP_EVENT_R_JOIN_IN]		= { .state = GARP_APPLICANT_QO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		[GARP_EVENT_R_JOIN_EMPTY]	= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		[GARP_EVENT_R_EMPTY]		= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		[GARP_EVENT_R_LEAVE_IN]		= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		[GARP_EVENT_R_LEAVE_EMPTY]	= { .state = GARP_APPLICANT_VO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		[GARP_EVENT_REQ_JOIN]		= { .state = GARP_APPLICANT_QP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		[GARP_EVENT_REQ_LEAVE]		= { .state = GARP_APPLICANT_INVALID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int garp_attr_cmp(const struct garp_attr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 			 const void *data, u8 len, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	if (attr->type != type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		return attr->type - type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	if (attr->dlen != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		return attr->dlen - len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	return memcmp(attr->data, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static struct garp_attr *garp_attr_lookup(const struct garp_applicant *app,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 					  const void *data, u8 len, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	struct rb_node *parent = app->gid.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	struct garp_attr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	int d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	while (parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		attr = rb_entry(parent, struct garp_attr, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		d = garp_attr_cmp(attr, data, len, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		if (d > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			parent = parent->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		else if (d < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			parent = parent->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 			return attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static struct garp_attr *garp_attr_create(struct garp_applicant *app,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 					  const void *data, u8 len, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	struct rb_node *parent = NULL, **p = &app->gid.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	struct garp_attr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	int d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		attr = rb_entry(parent, struct garp_attr, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		d = garp_attr_cmp(attr, data, len, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		if (d > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 			p = &parent->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		else if (d < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 			p = &parent->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			/* The attribute already exists; re-use it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			return attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		return attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	attr->state = GARP_APPLICANT_VO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	attr->type  = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	attr->dlen  = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	memcpy(attr->data, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	rb_link_node(&attr->node, parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	rb_insert_color(&attr->node, &app->gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	return attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static void garp_attr_destroy(struct garp_applicant *app, struct garp_attr *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	rb_erase(&attr->node, &app->gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	kfree(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void garp_attr_destroy_all(struct garp_applicant *app)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	struct rb_node *node, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	struct garp_attr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	for (node = rb_first(&app->gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	     next = node ? rb_next(node) : NULL, node != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	     node = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		attr = rb_entry(node, struct garp_attr, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		garp_attr_destroy(app, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static int garp_pdu_init(struct garp_applicant *app)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	struct garp_pdu_hdr *gp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #define LLC_RESERVE	sizeof(struct llc_pdu_un)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	skb = alloc_skb(app->dev->mtu + LL_RESERVED_SPACE(app->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	skb->dev = app->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	skb->protocol = htons(ETH_P_802_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	skb_reserve(skb, LL_RESERVED_SPACE(app->dev) + LLC_RESERVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	gp = __skb_put(skb, sizeof(*gp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	put_unaligned(htons(GARP_PROTOCOL_ID), &gp->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	app->pdu = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static int garp_pdu_append_end_mark(struct garp_applicant *app)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	if (skb_tailroom(app->pdu) < sizeof(u8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	__skb_put_u8(app->pdu, GARP_END_MARK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static void garp_pdu_queue(struct garp_applicant *app)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	if (!app->pdu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	garp_pdu_append_end_mark(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	garp_pdu_append_end_mark(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	llc_pdu_header_init(app->pdu, LLC_PDU_TYPE_U, LLC_SAP_BSPAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 			    LLC_SAP_BSPAN, LLC_PDU_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	llc_pdu_init_as_ui_cmd(app->pdu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	llc_mac_hdr_init(app->pdu, app->dev->dev_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			 app->app->proto.group_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	skb_queue_tail(&app->queue, app->pdu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	app->pdu = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static void garp_queue_xmit(struct garp_applicant *app)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	while ((skb = skb_dequeue(&app->queue)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		dev_queue_xmit(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int garp_pdu_append_msg(struct garp_applicant *app, u8 attrtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	struct garp_msg_hdr *gm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	if (skb_tailroom(app->pdu) < sizeof(*gm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	gm = __skb_put(app->pdu, sizeof(*gm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	gm->attrtype = attrtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	garp_cb(app->pdu)->cur_type = attrtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int garp_pdu_append_attr(struct garp_applicant *app,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 				const struct garp_attr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 				enum garp_attr_event event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	struct garp_attr_hdr *ga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	if (!app->pdu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		err = garp_pdu_init(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	if (garp_cb(app->pdu)->cur_type != attr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		if (garp_cb(app->pdu)->cur_type &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		    garp_pdu_append_end_mark(app) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 			goto queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		if (garp_pdu_append_msg(app, attr->type) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 			goto queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	len = sizeof(*ga) + attr->dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	if (skb_tailroom(app->pdu) < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		goto queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	ga = __skb_put(app->pdu, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	ga->len   = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	ga->event = event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	memcpy(ga->data, attr->data, attr->dlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) queue:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	garp_pdu_queue(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static void garp_attr_event(struct garp_applicant *app,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 			    struct garp_attr *attr, enum garp_event event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	enum garp_applicant_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	state = garp_applicant_state_table[attr->state][event].state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	if (state == GARP_APPLICANT_INVALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	switch (garp_applicant_state_table[attr->state][event].action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	case GARP_ACTION_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	case GARP_ACTION_S_JOIN_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		/* When appending the attribute fails, don't update state in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		 * order to retry on next TRANSMIT_PDU event. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		if (garp_pdu_append_attr(app, attr, GARP_JOIN_IN) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	case GARP_ACTION_S_LEAVE_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		garp_pdu_append_attr(app, attr, GARP_LEAVE_EMPTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		/* As a pure applicant, sending a leave message implies that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		 * the attribute was unregistered and can be destroyed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		garp_attr_destroy(app, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	attr->state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int garp_request_join(const struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		      const struct garp_application *appl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		      const void *data, u8 len, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	struct garp_port *port = rtnl_dereference(dev->garp_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	struct garp_attr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	spin_lock_bh(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	attr = garp_attr_create(app, data, len, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	if (!attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		spin_unlock_bh(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	garp_attr_event(app, attr, GARP_EVENT_REQ_JOIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	spin_unlock_bh(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) EXPORT_SYMBOL_GPL(garp_request_join);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) void garp_request_leave(const struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 			const struct garp_application *appl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 			const void *data, u8 len, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	struct garp_port *port = rtnl_dereference(dev->garp_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	struct garp_attr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	spin_lock_bh(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	attr = garp_attr_lookup(app, data, len, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	if (!attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		spin_unlock_bh(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	garp_attr_event(app, attr, GARP_EVENT_REQ_LEAVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	spin_unlock_bh(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) EXPORT_SYMBOL_GPL(garp_request_leave);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static void garp_gid_event(struct garp_applicant *app, enum garp_event event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	struct rb_node *node, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	struct garp_attr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	for (node = rb_first(&app->gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	     next = node ? rb_next(node) : NULL, node != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	     node = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		attr = rb_entry(node, struct garp_attr, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		garp_attr_event(app, attr, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static void garp_join_timer_arm(struct garp_applicant *app)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	unsigned long delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	delay = (u64)msecs_to_jiffies(garp_join_time) * prandom_u32() >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	mod_timer(&app->join_timer, jiffies + delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static void garp_join_timer(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	struct garp_applicant *app = from_timer(app, t, join_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	spin_lock(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	garp_gid_event(app, GARP_EVENT_TRANSMIT_PDU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	garp_pdu_queue(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	spin_unlock(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	garp_queue_xmit(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	garp_join_timer_arm(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int garp_pdu_parse_end_mark(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	if (!pskb_may_pull(skb, sizeof(u8)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	if (*skb->data == GARP_END_MARK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		skb_pull(skb, sizeof(u8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static int garp_pdu_parse_attr(struct garp_applicant *app, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 			       u8 attrtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	const struct garp_attr_hdr *ga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	struct garp_attr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	enum garp_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	unsigned int dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	if (!pskb_may_pull(skb, sizeof(*ga)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	ga = (struct garp_attr_hdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	if (ga->len < sizeof(*ga))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	if (!pskb_may_pull(skb, ga->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	skb_pull(skb, ga->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	dlen = sizeof(*ga) - ga->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	if (attrtype > app->app->maxattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	switch (ga->event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	case GARP_LEAVE_ALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		if (dlen != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		garp_gid_event(app, GARP_EVENT_R_LEAVE_EMPTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	case GARP_JOIN_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		event = GARP_EVENT_R_JOIN_EMPTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	case GARP_JOIN_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		event = GARP_EVENT_R_JOIN_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	case GARP_LEAVE_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		event = GARP_EVENT_R_LEAVE_EMPTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	case GARP_EMPTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		event = GARP_EVENT_R_EMPTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	if (dlen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	attr = garp_attr_lookup(app, ga->data, dlen, attrtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	if (attr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	garp_attr_event(app, attr, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static int garp_pdu_parse_msg(struct garp_applicant *app, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	const struct garp_msg_hdr *gm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	if (!pskb_may_pull(skb, sizeof(*gm)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	gm = (struct garp_msg_hdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	if (gm->attrtype == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	skb_pull(skb, sizeof(*gm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	while (skb->len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		if (garp_pdu_parse_attr(app, skb, gm->attrtype) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		if (garp_pdu_parse_end_mark(skb) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static void garp_pdu_rcv(const struct stp_proto *proto, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 			 struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	struct garp_application *appl = proto->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	struct garp_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	struct garp_applicant *app;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	const struct garp_pdu_hdr *gp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	port = rcu_dereference(dev->garp_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	if (!port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	app = rcu_dereference(port->applicants[appl->type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	if (!app)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	if (!pskb_may_pull(skb, sizeof(*gp)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	gp = (struct garp_pdu_hdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	if (get_unaligned(&gp->protocol) != htons(GARP_PROTOCOL_ID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	skb_pull(skb, sizeof(*gp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	spin_lock(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	while (skb->len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		if (garp_pdu_parse_msg(app, skb) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		if (garp_pdu_parse_end_mark(skb) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	spin_unlock(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static int garp_init_port(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	struct garp_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	port = kzalloc(sizeof(*port), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	if (!port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	rcu_assign_pointer(dev->garp_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static void garp_release_port(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	struct garp_port *port = rtnl_dereference(dev->garp_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	for (i = 0; i <= GARP_APPLICATION_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 		if (rtnl_dereference(port->applicants[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	RCU_INIT_POINTER(dev->garp_port, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	kfree_rcu(port, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int garp_init_applicant(struct net_device *dev, struct garp_application *appl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	struct garp_applicant *app;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	if (!rtnl_dereference(dev->garp_port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 		err = garp_init_port(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 			goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	app = kzalloc(sizeof(*app), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	if (!app)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 		goto err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	err = dev_mc_add(dev, appl->proto.group_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		goto err3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	app->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	app->app = appl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	app->gid = RB_ROOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	spin_lock_init(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	skb_queue_head_init(&app->queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	rcu_assign_pointer(dev->garp_port->applicants[appl->type], app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	timer_setup(&app->join_timer, garp_join_timer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	garp_join_timer_arm(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) err3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	kfree(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) err2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	garp_release_port(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) err1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) EXPORT_SYMBOL_GPL(garp_init_applicant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	struct garp_port *port = rtnl_dereference(dev->garp_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	struct garp_applicant *app = rtnl_dereference(port->applicants[appl->type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	RCU_INIT_POINTER(port->applicants[appl->type], NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	/* Delete timer and generate a final TRANSMIT_PDU event to flush out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	 * all pending messages before the applicant is gone. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	del_timer_sync(&app->join_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	spin_lock_bh(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	garp_gid_event(app, GARP_EVENT_TRANSMIT_PDU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	garp_attr_destroy_all(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	garp_pdu_queue(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	spin_unlock_bh(&app->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	garp_queue_xmit(app);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	dev_mc_del(dev, appl->proto.group_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	kfree_rcu(app, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	garp_release_port(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) EXPORT_SYMBOL_GPL(garp_uninit_applicant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) int garp_register_application(struct garp_application *appl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	appl->proto.rcv = garp_pdu_rcv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	appl->proto.data = appl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	return stp_proto_register(&appl->proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) EXPORT_SYMBOL_GPL(garp_register_application);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) void garp_unregister_application(struct garp_application *appl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	stp_proto_unregister(&appl->proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) EXPORT_SYMBOL_GPL(garp_unregister_application);