1- /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
1+ /* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
22
33 This program is free software; you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
1919static struct blockdata * keyblock_free ;
2020static unsigned int blockdata_count , blockdata_hwm , blockdata_alloced ;
2121
22- static void blockdata_expand (int n )
22+ static void add_blocks (int n )
2323{
2424 struct blockdata * new = whine_malloc (n * sizeof (struct blockdata ));
2525
@@ -47,7 +47,7 @@ void blockdata_init(void)
4747
4848 /* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
4949 if (option_bool (OPT_DNSSEC_VALID ))
50- blockdata_expand (daemon -> cachesize );
50+ add_blocks (daemon -> cachesize );
5151}
5252
5353void blockdata_report (void )
@@ -58,50 +58,61 @@ void blockdata_report(void)
5858 blockdata_alloced * sizeof (struct blockdata ));
5959}
6060
61+ static struct blockdata * new_block (void )
62+ {
63+ struct blockdata * block ;
64+
65+ if (!keyblock_free )
66+ add_blocks (50 );
67+
68+ if (keyblock_free )
69+ {
70+ block = keyblock_free ;
71+ keyblock_free = block -> next ;
72+ blockdata_count ++ ;
73+ if (blockdata_hwm < blockdata_count )
74+ blockdata_hwm = blockdata_count ;
75+ block -> next = NULL ;
76+ return block ;
77+ }
78+
79+ return NULL ;
80+ }
81+
6182static struct blockdata * blockdata_alloc_real (int fd , char * data , size_t len )
6283{
6384 struct blockdata * block , * ret = NULL ;
6485 struct blockdata * * prev = & ret ;
6586 size_t blen ;
6687
67- while ( len > 0 )
88+ do
6889 {
69- if (!keyblock_free )
70- blockdata_expand (50 );
71-
72- if (keyblock_free )
73- {
74- block = keyblock_free ;
75- keyblock_free = block -> next ;
76- blockdata_count ++ ;
77- }
78- else
90+ if (!(block = new_block ()))
7991 {
8092 /* failed to alloc, free partial chain */
8193 blockdata_free (ret );
8294 return NULL ;
8395 }
84-
85- if (blockdata_hwm < blockdata_count )
86- blockdata_hwm = blockdata_count ;
87-
88- blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len ;
89- if (data )
90- {
91- memcpy (block -> key , data , blen );
92- data += blen ;
93- }
94- else if (!read_write (fd , block -> key , blen , 1 ))
96+
97+ if ((blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len ) > 0 )
9598 {
96- /* failed read free partial chain */
97- blockdata_free (ret );
98- return NULL ;
99+ if (data )
100+ {
101+ memcpy (block -> key , data , blen );
102+ data += blen ;
103+ }
104+ else if (!read_write (fd , block -> key , blen , 1 ))
105+ {
106+ /* failed read free partial chain */
107+ blockdata_free (ret );
108+ return NULL ;
109+ }
99110 }
111+
100112 len -= blen ;
101113 * prev = block ;
102114 prev = & block -> next ;
103- block -> next = NULL ;
104- }
115+ } while (len != 0 );
105116
106117 return ret ;
107118}
@@ -111,6 +122,58 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
111122 return blockdata_alloc_real (0 , data , len );
112123}
113124
125+ /* Add data to the end of the block.
126+ newlen is length of new data, NOT total new length.
127+ Use blockdata_alloc(NULL, 0) to make empty block to add to. */
128+ int blockdata_expand (struct blockdata * block , size_t oldlen , char * data , size_t newlen )
129+ {
130+ struct blockdata * b ;
131+
132+ /* find size of current final block */
133+ for (b = block ; oldlen > KEYBLOCK_LEN && b ; b = b -> next , oldlen -= KEYBLOCK_LEN );
134+
135+ /* chain to short for length, something is broken */
136+ if (oldlen > KEYBLOCK_LEN )
137+ {
138+ blockdata_free (block );
139+ return 0 ;
140+ }
141+
142+ while (1 )
143+ {
144+ struct blockdata * new ;
145+ size_t blocksize = KEYBLOCK_LEN - oldlen ;
146+ size_t size = (newlen <= blocksize ) ? newlen : blocksize ;
147+
148+ if (size != 0 )
149+ {
150+ memcpy (& b -> key [oldlen ], data , size );
151+ data += size ;
152+ newlen -= size ;
153+ }
154+
155+ /* full blocks from now on. */
156+ oldlen = 0 ;
157+
158+ if (newlen == 0 )
159+ break ;
160+
161+ if ((new = new_block ()))
162+ {
163+ b -> next = new ;
164+ b = new ;
165+ }
166+ else
167+ {
168+ /* failed to alloc, free partial chain */
169+ blockdata_free (block );
170+ return 0 ;
171+ }
172+ }
173+
174+ return 1 ;
175+ }
176+
114177void blockdata_free (struct blockdata * blocks )
115178{
116179 struct blockdata * tmp ;
0 commit comments