@@ -64,38 +64,50 @@ struct afs_addr_list *afs_alloc_addrlist(unsigned int nr,
64
64
/*
65
65
* Parse a text string consisting of delimited addresses.
66
66
*/
67
- struct afs_addr_list * afs_parse_text_addrs (const char * text , size_t len ,
68
- char delim ,
69
- unsigned short service ,
70
- unsigned short port )
67
+ struct afs_vlserver_list * afs_parse_text_addrs (struct afs_net * net ,
68
+ const char * text , size_t len ,
69
+ char delim ,
70
+ unsigned short service ,
71
+ unsigned short port )
71
72
{
73
+ struct afs_vlserver_list * vllist ;
72
74
struct afs_addr_list * alist ;
73
75
const char * p , * end = text + len ;
76
+ const char * problem ;
74
77
unsigned int nr = 0 ;
78
+ int ret = - ENOMEM ;
75
79
76
80
_enter ("%*.*s,%c" , (int )len , (int )len , text , delim );
77
81
78
- if (!len )
82
+ if (!len ) {
83
+ _leave (" = -EDESTADDRREQ [empty]" );
79
84
return ERR_PTR (- EDESTADDRREQ );
85
+ }
80
86
81
87
if (delim == ':' && (memchr (text , ',' , len ) || !memchr (text , '.' , len )))
82
88
delim = ',' ;
83
89
84
90
/* Count the addresses */
85
91
p = text ;
86
92
do {
87
- if (!* p )
88
- return ERR_PTR (- EINVAL );
93
+ if (!* p ) {
94
+ problem = "nul" ;
95
+ goto inval ;
96
+ }
89
97
if (* p == delim )
90
98
continue ;
91
99
nr ++ ;
92
100
if (* p == '[' ) {
93
101
p ++ ;
94
- if (p == end )
95
- return ERR_PTR (- EINVAL );
102
+ if (p == end ) {
103
+ problem = "brace1" ;
104
+ goto inval ;
105
+ }
96
106
p = memchr (p , ']' , end - p );
97
- if (!p )
98
- return ERR_PTR (- EINVAL );
107
+ if (!p ) {
108
+ problem = "brace2" ;
109
+ goto inval ;
110
+ }
99
111
p ++ ;
100
112
if (p >= end )
101
113
break ;
@@ -109,10 +121,19 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
109
121
110
122
_debug ("%u/%u addresses" , nr , AFS_MAX_ADDRESSES );
111
123
112
- alist = afs_alloc_addrlist ( nr , service , port );
113
- if (!alist )
124
+ vllist = afs_alloc_vlserver_list ( 1 );
125
+ if (!vllist )
114
126
return ERR_PTR (- ENOMEM );
115
127
128
+ vllist -> nr_servers = 1 ;
129
+ vllist -> servers [0 ].server = afs_alloc_vlserver ("<dummy>" , 7 , AFS_VL_PORT );
130
+ if (!vllist -> servers [0 ].server )
131
+ goto error_vl ;
132
+
133
+ alist = afs_alloc_addrlist (nr , service , AFS_VL_PORT );
134
+ if (!alist )
135
+ goto error ;
136
+
116
137
/* Extract the addresses */
117
138
p = text ;
118
139
do {
@@ -135,17 +156,21 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
135
156
break ;
136
157
}
137
158
138
- if (in4_pton (p , q - p , (u8 * )& x [0 ], -1 , & stop ))
159
+ if (in4_pton (p , q - p , (u8 * )& x [0 ], -1 , & stop )) {
139
160
family = AF_INET ;
140
- else if (in6_pton (p , q - p , (u8 * )x , -1 , & stop ))
161
+ } else if (in6_pton (p , q - p , (u8 * )x , -1 , & stop )) {
141
162
family = AF_INET6 ;
142
- else
163
+ } else {
164
+ problem = "family" ;
143
165
goto bad_address ;
166
+ }
144
167
145
- if (stop != q )
168
+ p = q ;
169
+ if (stop != p ) {
170
+ problem = "nostop" ;
146
171
goto bad_address ;
172
+ }
147
173
148
- p = q ;
149
174
if (q < end && * q == ']' )
150
175
p ++ ;
151
176
@@ -154,18 +179,23 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
154
179
/* Port number specification "+1234" */
155
180
xport = 0 ;
156
181
p ++ ;
157
- if (p >= end || !isdigit (* p ))
182
+ if (p >= end || !isdigit (* p )) {
183
+ problem = "port" ;
158
184
goto bad_address ;
185
+ }
159
186
do {
160
187
xport *= 10 ;
161
188
xport += * p - '0' ;
162
- if (xport > 65535 )
189
+ if (xport > 65535 ) {
190
+ problem = "pval" ;
163
191
goto bad_address ;
192
+ }
164
193
p ++ ;
165
194
} while (p < end && isdigit (* p ));
166
195
} else if (* p == delim ) {
167
196
p ++ ;
168
197
} else {
198
+ problem = "weird" ;
169
199
goto bad_address ;
170
200
}
171
201
}
@@ -177,12 +207,23 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
177
207
178
208
} while (p < end );
179
209
210
+ rcu_assign_pointer (vllist -> servers [0 ].server -> addresses , alist );
180
211
_leave (" = [nr %u]" , alist -> nr_addrs );
181
- return alist ;
212
+ return vllist ;
182
213
183
- bad_address :
184
- kfree (alist );
214
+ inval :
215
+ _leave (" = -EINVAL [%s %zu %*.*s]" ,
216
+ problem , p - text , (int )len , (int )len , text );
185
217
return ERR_PTR (- EINVAL );
218
+ bad_address :
219
+ _leave (" = -EINVAL [%s %zu %*.*s]" ,
220
+ problem , p - text , (int )len , (int )len , text );
221
+ ret = - EINVAL ;
222
+ error :
223
+ afs_put_addrlist (alist );
224
+ error_vl :
225
+ afs_put_vlserverlist (net , vllist );
226
+ return ERR_PTR (ret );
186
227
}
187
228
188
229
/*
@@ -201,30 +242,34 @@ static int afs_cmp_addr_list(const struct afs_addr_list *a1,
201
242
/*
202
243
* Perform a DNS query for VL servers and build a up an address list.
203
244
*/
204
- struct afs_addr_list * afs_dns_query (struct afs_cell * cell , time64_t * _expiry )
245
+ struct afs_vlserver_list * afs_dns_query (struct afs_cell * cell , time64_t * _expiry )
205
246
{
206
- struct afs_addr_list * alist ;
207
- char * vllist = NULL ;
247
+ struct afs_vlserver_list * vllist ;
248
+ char * result = NULL ;
208
249
int ret ;
209
250
210
251
_enter ("%s" , cell -> name );
211
252
212
- ret = dns_query ("afsdb" , cell -> name , cell -> name_len ,
213
- "" , & vllist , _expiry );
214
- if (ret < 0 )
253
+ ret = dns_query ("afsdb" , cell -> name , cell -> name_len , "srv=1" ,
254
+ & result , _expiry );
255
+ if (ret < 0 ) {
256
+ _leave (" = %d [dns]" , ret );
215
257
return ERR_PTR (ret );
216
-
217
- alist = afs_parse_text_addrs (vllist , strlen (vllist ), ',' ,
218
- VL_SERVICE , AFS_VL_PORT );
219
- if (IS_ERR (alist )) {
220
- kfree (vllist );
221
- if (alist != ERR_PTR (- ENOMEM ))
222
- pr_err ("Failed to parse DNS data\n" );
223
- return alist ;
224
258
}
225
259
226
- kfree (vllist );
227
- return alist ;
260
+ if (* _expiry == 0 )
261
+ * _expiry = ktime_get_real_seconds () + 60 ;
262
+
263
+ if (ret > 1 && result [0 ] == 0 )
264
+ vllist = afs_extract_vlserver_list (cell , result , ret );
265
+ else
266
+ vllist = afs_parse_text_addrs (cell -> net , result , ret , ',' ,
267
+ VL_SERVICE , AFS_VL_PORT );
268
+ kfree (result );
269
+ if (IS_ERR (vllist ) && vllist != ERR_PTR (- ENOMEM ))
270
+ pr_err ("Failed to parse DNS data %ld\n" , PTR_ERR (vllist ));
271
+
272
+ return vllist ;
228
273
}
229
274
230
275
/*
@@ -347,43 +392,3 @@ int afs_end_cursor(struct afs_addr_cursor *ac)
347
392
ac -> begun = false;
348
393
return ac -> error ;
349
394
}
350
-
351
- /*
352
- * Set the address cursor for iterating over VL servers.
353
- */
354
- int afs_set_vl_cursor (struct afs_addr_cursor * ac , struct afs_cell * cell )
355
- {
356
- struct afs_addr_list * alist ;
357
- int ret ;
358
-
359
- if (!rcu_access_pointer (cell -> vl_addrs )) {
360
- ret = wait_on_bit (& cell -> flags , AFS_CELL_FL_NO_LOOKUP_YET ,
361
- TASK_INTERRUPTIBLE );
362
- if (ret < 0 )
363
- return ret ;
364
-
365
- if (!rcu_access_pointer (cell -> vl_addrs ) &&
366
- ktime_get_real_seconds () < cell -> dns_expiry )
367
- return cell -> error ;
368
- }
369
-
370
- read_lock (& cell -> vl_addrs_lock );
371
- alist = rcu_dereference_protected (cell -> vl_addrs ,
372
- lockdep_is_held (& cell -> vl_addrs_lock ));
373
- if (alist -> nr_addrs > 0 )
374
- afs_get_addrlist (alist );
375
- else
376
- alist = NULL ;
377
- read_unlock (& cell -> vl_addrs_lock );
378
-
379
- if (!alist )
380
- return - EDESTADDRREQ ;
381
-
382
- ac -> alist = alist ;
383
- ac -> addr = NULL ;
384
- ac -> start = READ_ONCE (alist -> index );
385
- ac -> index = ac -> start ;
386
- ac -> error = 0 ;
387
- ac -> begun = false;
388
- return 0 ;
389
- }
0 commit comments