@@ -62,22 +62,35 @@ class DynDNS12UpdateView(generics.GenericAPIView):
6262 serializer_class = RRsetSerializer
6363 throttle_scope = "dyndns"
6464
65+ IPV4_PARAMS = ["myip" , "myipv4" , "ip" ]
66+ IPV6_PARAMS = ["myipv6" , "ipv6" , "myip" , "ip" ]
67+
6568 @property
6669 def throttle_scope_bucket (self ):
6770 return self .domain .name
6871
69- def _find_action (self , param_keys , separator ) -> UpdateAction :
72+ def _find_action (
73+ self , param_keys , separator , use_remote_ip_fallback = False
74+ ) -> UpdateAction :
7075 """
7176 Parses the request for IP parameters and determines the appropriate update action.
7277
73- This method checks a given list of parameter keys in the request URL. It handles
74- plain IP addresses, comma-separated lists of IPs, the "preserve" keyword, and
75- subnet notation (e.g., "10.0.0.0/24"). It also uses the client's remote IP
76- as a fallback.
78+ This method checks a given list of parameter keys in the request URL. The keys can
79+ be global (e.g. ['myip']) or scoped to a specific hostname (e.g. ['example.com.myip']).
80+
81+ It handles plain IP addresses, comma-separated lists of IPs, the "preserve" keyword,
82+ and subnet notation (e.g., "10.0.0.0/24").
83+
84+ Args:
85+ param_keys (list): A list of parameter keys to check for in the request.
86+ separator (str): The IP address separator ("." for IPv4, ":" for IPv6).
87+ use_remote_ip_fallback (bool): If True, uses the client's remote IP as a
88+ fallback if no other parameters are found.
7789
7890 Returns:
79- UpdateAction: A dataclass instance (`SetIPs`, `UpdateWithSubnet`, or `PreserveIPs`)
80- representing the action to be taken.
91+ UpdateAction or None: A dataclass instance (`SetIPs`, `UpdateWithSubnet`, or
92+ `PreserveIPs`) representing the action to be taken, or None if no relevant
93+ parameter was found and the fallback to client IP is disabled.
8194 """
8295 # Check URL parameters
8396 for param_key in param_keys :
@@ -119,12 +132,13 @@ def _find_action(self, param_keys, separator) -> UpdateAction:
119132 return SetIPs (ips = params )
120133
121134 # Check remote IP address
122- client_ip = self .request .META .get ("REMOTE_ADDR" )
123- if separator in client_ip :
124- return SetIPs (ips = [client_ip ])
135+ if use_remote_ip_fallback :
136+ client_ip = self .request .META .get ("REMOTE_ADDR" )
137+ if separator in client_ip :
138+ return SetIPs (ips = [client_ip ])
125139
126140 # give up
127- return SetIPs ( ips = [])
141+ return None
128142
129143 @staticmethod
130144 def _sanitize_qnames (qnames_str ) -> set [str ]:
@@ -245,12 +259,26 @@ def get(self, request, *args, **kwargs) -> Response:
245259 grouped_records [rrset .subname ].extend (rrset .records .all ())
246260
247261 actions = {
248- "A" : self ._find_action (["myip" , "myipv4" , "ip" ], separator = "." ),
249- "AAAA" : self ._find_action (["myipv6" , "ipv6" , "myip" , "ip" ], separator = ":" ),
262+ "A" : self ._find_action (
263+ self .IPV4_PARAMS , separator = "." , use_remote_ip_fallback = True
264+ )
265+ or SetIPs (ips = []),
266+ "AAAA" : self ._find_action (
267+ self .IPV6_PARAMS , separator = ":" , use_remote_ip_fallback = True
268+ )
269+ or SetIPs (ips = []),
250270 }
251271
252272 data = []
253- for subname in self .subnames :
273+ for qname , subname in zip (self .qnames , self .subnames ):
274+ scoped_ipv4_params = [f"{ qname } .{ p } " for p in self .IPV4_PARAMS ]
275+ scoped_ipv6_params = [f"{ qname } .{ p } " for p in self .IPV6_PARAMS ]
276+ domain_actions = {
277+ "A" : self ._find_action (scoped_ipv4_params , separator = "." )
278+ or actions ["A" ],
279+ "AAAA" : self ._find_action (scoped_ipv6_params , separator = ":" )
280+ or actions ["AAAA" ],
281+ }
254282 subname_records = grouped_records .get (subname , [])
255283
256284 data += [
@@ -260,7 +288,7 @@ def get(self, request, *args, **kwargs) -> Response:
260288 "ttl" : 60 ,
261289 "records" : records ,
262290 }
263- for type_ , action in actions .items ()
291+ for type_ , action in domain_actions .items ()
264292 if (records := self ._get_records (subname_records , action )) is not None
265293 ]
266294
0 commit comments