summaryrefslogtreecommitdiffstats
path: root/net/netbeui/netbeui_name.c
blob: d47fddd1b148aa9b863e389c04dfd9bd3e7ca434 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 *	NetBIOS name handler
 */

/*
 *	You must hold the netbios name lock before using these.
 */
  
struct nb_name *nb_name_find(struct device *dev,const char * name)
{
	struct nb_name *nb=nb_name_list;
	while(nb!=NULL)
	{
		if((dev==NULL || dev==nb->dev) && 
			strncmp(name,nb->name, NB_NAME_LEN)==0)
			return nb;
		nb=nb->next;
	}
	return NULL;
}

int nb_name_add(struct device *dev, const char *name, int ours, int pri)
{
	struct nb_name *nb=kmalloc(sizeof(*nb), pri);
	if(nb==NULL)
		return NULL;
	nb->dev=dev;
	strncpy(nb->name,name,NB_NAME_LEN);
	nb->name[NB_NAME_LEN-1]=0;
	nb->next=nb_name_list;
	nb->ours=ours;
	nb_name_list=nb;
}

void nb_name_delete(struct nb_name *nb)
{
	struct nb_name *i=&nb_name_list;
	while((*i)!=NULL)
	{
		if(*i==nb)
		{
			*i=nb->next;
			kfree_s(nb,sizeof(*nb));
			return;
		}
		i=&((*i)->next);
	}
	printk(KERN_ERR "nb_name_delete: bad name pointer!\n");
}

/*
 *	NETBIOS name handlers
 */

static void nb_defend(struct device *dev, const char *name)
{
	struct sk_buff *nskb=nb_alloc_skb(NB_CONTROL_LEN, GFP_ATOMIC);
	if(nskb==NULL)
		return;
	/* Build a name defence packet */
	dev_queue_xmit(nskb,dev,SOPRI_INTERACTIVE);
}

void netbeui_heard_name(struct device *dev, struct sk_buff *skb)
{
	struct nb_name *nb;
	name=...
	
	if((nb=nb_name_find(dev,name))!=NULL)
	{
		/*
		 *	If we own the name then defend it
		 */
		if(nb->our && !nb->state==NB_ACQUIRE)
			nb_defend(dev,name);
		/*
		 *	A name has been resolved. Wake up pending
		 *	connectors.
		 */
		if(nb->state==NB_QUERY)
		{
			nb->state=NB_OTHER;
			nb_complete(nb,skb);
		}
	}
	kfree_skb(skb, FREE_READ);
	return 0;
}

/*
 *	Handle incoming name defences
 */
 
void netbeui_name_defence(struct dev *dev, struct sk_buff *skb)
{
	struct nb_name *name;
	name=
	
	if((nb=nb_name_find(dev,name))!=NULL)
	{
		if(nb->ours)
		{
			/*	
			 *	We wanted it, we got told its used
			 */
			if(nb->state==NB_ACQUIRE)
			{
				/*
				 *	Fill in the record for its true
				 *	owner. Set the state first as
				 *	nb_complete may well delete the
				 *	record.
				 */
				nb->state=NB_OTHER;
				nb_complete(nb,skb);
				nb_wakeup();
			}
			/*
			 *	We own it we got told its used. This is
			 *	a deep cack even that can only occur when
			 *	a bridge comes back and the net was split.
			 *	Make sure both sides lose.
			 */
			if(nb->state==NB_OURS || nb->state==NB_COLLIDE)
			{
				nb->state=NR_COLLIDE;
				nb_wakeup();
				/*
				 *	Kill the other copy too
				 */
				nb_defend(dev,name);	
				/*
				 *	Timer expiry will delete our
				 *	record.
				 */	
				nb_start_timer(nb, NB_TIME_COLLIDED);
			}		
		}
	}
	kfree_skb(skb, FREE_READ);
}

void netbeui_name_query(struct dev *dev, struct sk_buff *skb)
{
	char *name=...
	struct nb_name *nb=nb_find_name(dev,name);
	
	if(nb!=NULL && nb->ours)
	{
		struct sk_buff *nskb=nb_alloc_skb(NB_CONTROL_LEN, GFP_ATOMIC);
		if(nskb!=NULL)
		{
			/* Build a name reply packet */
			dev_queue_xmit(nskb,dev,SOPRI_INTERACTIVE);
		}
	}
	kfree_skb(skb, FREE_READ);
}