tcp_subr.c (b6919741b7479fab6886ae76ec151f4103bcf350) | tcp_subr.c (859f0f0d6bf753c16caa0103a541c69fb6bd5e37) |
---|---|
1/*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 1158 unchanged lines hidden (view full) --- 1167 * the failure. 1168 * 1169 * Returns 0 on success, or an error code on failure. 1170 */ 1171int 1172register_tcp_functions_as_names(struct tcp_function_block *blk, int wait, 1173 const char *names[], int *num_names) 1174{ | 1/*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 1158 unchanged lines hidden (view full) --- 1167 * the failure. 1168 * 1169 * Returns 0 on success, or an error code on failure. 1170 */ 1171int 1172register_tcp_functions_as_names(struct tcp_function_block *blk, int wait, 1173 const char *names[], int *num_names) 1174{ |
1175 struct tcp_function *n; | 1175 struct tcp_function *f[TCP_FUNCTION_NAME_NUM_MAX]; |
1176 struct tcp_function_set fs; | 1176 struct tcp_function_set fs; |
1177 int error, i; | 1177 int error, i, num_registered; |
1178 1179 KASSERT(names != NULL, ("%s: Called with NULL name list", __func__)); 1180 KASSERT(*num_names > 0, 1181 ("%s: Called with non-positive length of name list", __func__)); 1182 KASSERT(rw_initialized(&tcp_function_lock), 1183 ("%s: called too early", __func__)); 1184 | 1178 1179 KASSERT(names != NULL, ("%s: Called with NULL name list", __func__)); 1180 KASSERT(*num_names > 0, 1181 ("%s: Called with non-positive length of name list", __func__)); 1182 KASSERT(rw_initialized(&tcp_function_lock), 1183 ("%s: called too early", __func__)); 1184 |
1185 if (*num_names > TCP_FUNCTION_NAME_NUM_MAX) { 1186 /* Too many names. */ 1187 *num_names = 0; 1188 return (E2BIG); 1189 } |
|
1185 if ((blk->tfb_tcp_output == NULL) || 1186 (blk->tfb_tcp_do_segment == NULL) || 1187 (blk->tfb_tcp_ctloutput == NULL) || 1188 (blk->tfb_tcp_handoff_ok == NULL) || 1189 (strlen(blk->tfb_tcp_block_name) == 0)) { | 1190 if ((blk->tfb_tcp_output == NULL) || 1191 (blk->tfb_tcp_do_segment == NULL) || 1192 (blk->tfb_tcp_ctloutput == NULL) || 1193 (blk->tfb_tcp_handoff_ok == NULL) || 1194 (strlen(blk->tfb_tcp_block_name) == 0)) { |
1190 /* 1191 * These functions are required and you 1192 * need a name. 1193 */ | 1195 /* These functions are required and a name is needed. */ |
1194 *num_names = 0; 1195 return (EINVAL); 1196 } 1197 | 1196 *num_names = 0; 1197 return (EINVAL); 1198 } 1199 |
1198 if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) { 1199 *num_names = 0; 1200 return (EINVAL); | 1200 for (i = 0; i < *num_names; i++) { 1201 f[i] = malloc(sizeof(struct tcp_function), M_TCPFUNCTIONS, wait); 1202 if (f[i] == NULL) { 1203 while (--i >= 0) 1204 free(f[i], M_TCPFUNCTIONS); 1205 *num_names = 0; 1206 return (ENOMEM); 1207 } |
1201 } 1202 | 1208 } 1209 |
1210 num_registered = 0; 1211 rw_wlock(&tcp_function_lock); 1212 if (find_tcp_fb_locked(blk, NULL) != NULL) { 1213 /* A TCP function block can only be registered once. */ 1214 error = EALREADY; 1215 goto cleanup; 1216 } 1217 if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) { 1218 error = EINVAL; 1219 goto cleanup; 1220 } |
|
1203 refcount_init(&blk->tfb_refcnt, 0); 1204 blk->tfb_id = atomic_fetchadd_int(&next_tcp_stack_id, 1); 1205 for (i = 0; i < *num_names; i++) { | 1221 refcount_init(&blk->tfb_refcnt, 0); 1222 blk->tfb_id = atomic_fetchadd_int(&next_tcp_stack_id, 1); 1223 for (i = 0; i < *num_names; i++) { |
1206 n = malloc(sizeof(struct tcp_function), M_TCPFUNCTIONS, wait); 1207 if (n == NULL) { 1208 error = ENOMEM; 1209 goto cleanup; 1210 } 1211 n->tf_fb = blk; 1212 | |
1213 (void)strlcpy(fs.function_set_name, names[i], 1214 sizeof(fs.function_set_name)); | 1224 (void)strlcpy(fs.function_set_name, names[i], 1225 sizeof(fs.function_set_name)); |
1215 rw_wlock(&tcp_function_lock); | |
1216 if (find_tcp_functions_locked(&fs) != NULL) { 1217 /* Duplicate name space not allowed */ | 1226 if (find_tcp_functions_locked(&fs) != NULL) { 1227 /* Duplicate name space not allowed */ |
1218 rw_wunlock(&tcp_function_lock); 1219 free(n, M_TCPFUNCTIONS); | |
1220 error = EALREADY; 1221 goto cleanup; 1222 } | 1228 error = EALREADY; 1229 goto cleanup; 1230 } |
1223 (void)strlcpy(n->tf_name, names[i], sizeof(n->tf_name)); 1224 TAILQ_INSERT_TAIL(&t_functions, n, tf_next); | 1231 f[i]->tf_fb = blk; 1232 (void)strlcpy(f[i]->tf_name, names[i], sizeof(f[i]->tf_name)); 1233 TAILQ_INSERT_TAIL(&t_functions, f[i], tf_next); |
1225 tcp_fb_cnt++; | 1234 tcp_fb_cnt++; |
1226 rw_wunlock(&tcp_function_lock); | 1235 num_registered++; |
1227 } | 1236 } |
1237 rw_wunlock(&tcp_function_lock); |
|
1228 return (0); 1229 1230cleanup: | 1238 return (0); 1239 1240cleanup: |
1231 /* 1232 * Deregister the names we just added. Because registration failed 1233 * for names[i], we don't need to deregister that name. 1234 */ 1235 *num_names = i; 1236 rw_wlock(&tcp_function_lock); 1237 while (--i >= 0) { 1238 TAILQ_FOREACH(n, &t_functions, tf_next) { 1239 if (!strncmp(n->tf_name, names[i], 1240 TCP_FUNCTION_NAME_LEN_MAX)) { 1241 TAILQ_REMOVE(&t_functions, n, tf_next); 1242 tcp_fb_cnt--; 1243 n->tf_fb = NULL; 1244 free(n, M_TCPFUNCTIONS); 1245 break; 1246 } | 1241 /* Remove the entries just added. */ 1242 for (i = 0; i < *num_names; i++) { 1243 if (i < num_registered) { 1244 TAILQ_REMOVE(&t_functions, f[i], tf_next); 1245 tcp_fb_cnt--; |
1247 } | 1246 } |
1247 f[i]->tf_fb = NULL; 1248 free(f[i], M_TCPFUNCTIONS); |
|
1248 } 1249 rw_wunlock(&tcp_function_lock); | 1249 } 1250 rw_wunlock(&tcp_function_lock); |
1251 *num_names = num_registered; |
|
1250 return (error); 1251} 1252 1253/* 1254 * Register a TCP function block using the name provided in the name 1255 * argument. 1256 * 1257 * Returns 0 on success, or an error code on failure. --- 3473 unchanged lines hidden --- | 1252 return (error); 1253} 1254 1255/* 1256 * Register a TCP function block using the name provided in the name 1257 * argument. 1258 * 1259 * Returns 0 on success, or an error code on failure. --- 3473 unchanged lines hidden --- |