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 ---