@@ -120,13 +120,76 @@ xtables_options_xfrm(struct option *orig_opts, struct option *oldopts,
120120 memcpy (mp , oldopts , sizeof (* mp ) * num_old );
121121 mp += num_old ;
122122 }
123- xtables_free_opts (0 );
123+ if (xt_params -> opts != NULL && xt_params -> opts != xt_params -> orig_opts )
124+ xtables_free_opts (0 );
124125
125126 /* Clear trailing entry */
126127 memset (mp , 0 , sizeof (* mp ));
127128 return merge ;
128129}
129130
131+ struct option *
132+ xs_merge_options (struct option * orig_opts , struct option * oldopts ,
133+ const struct option * newopts , unsigned int * option_offset )
134+ {
135+ unsigned int num_orig = 0 , num_old = 0 , num_new = 0 , i ;
136+ struct option * merge ;
137+ struct option * mp ;
138+ struct option * old_base = oldopts ;
139+
140+ if (newopts == NULL || newopts -> name == NULL )
141+ return oldopts ;
142+
143+ if (orig_opts != NULL )
144+ for (; orig_opts [num_orig ].name != NULL ; ++ num_orig )
145+ ;
146+
147+ if (oldopts != NULL )
148+ for (; oldopts [num_old ].name != NULL ; ++ num_old )
149+ ;
150+
151+ for (; newopts [num_new ].name != NULL ; ++ num_new )
152+ ;
153+
154+ if (oldopts != NULL && num_old >= num_orig ) {
155+ oldopts += num_orig ;
156+ num_old -= num_orig ;
157+ } else {
158+ oldopts = NULL ;
159+ num_old = 0 ;
160+ }
161+
162+ merge = malloc (sizeof (* merge ) * (num_orig + num_new + num_old + 1 ));
163+ if (merge == NULL )
164+ return NULL ;
165+
166+ if (num_orig != 0 )
167+ memcpy (merge , orig_opts , sizeof (* merge ) * num_orig );
168+ mp = merge + num_orig ;
169+
170+ xt_params -> option_offset += XT_OPTION_OFFSET_SCALE ;
171+ * option_offset = xt_params -> option_offset ;
172+
173+ for (i = 0 ; i < num_new ; ++ i , ++ mp ) {
174+ mp -> name = newopts [i ].name ;
175+ mp -> has_arg = newopts [i ].has_arg ;
176+ mp -> flag = newopts [i ].flag ;
177+ mp -> val = newopts [i ].val + * option_offset ;
178+ }
179+
180+ if (oldopts != NULL && num_old != 0 ) {
181+ memcpy (mp , oldopts , sizeof (* mp ) * num_old );
182+ mp += num_old ;
183+ }
184+
185+ memset (mp , 0 , sizeof (* mp ));
186+
187+ if (old_base != NULL && old_base != orig_opts && old_base != xt_params -> orig_opts )
188+ free (old_base );
189+
190+ return merge ;
191+ }
192+
130193/**
131194 * Give the upper limit for a certain type.
132195 */
0 commit comments