r23183: Check in a change made by Tridge:
[tprouty/samba.git] / source / utils / net_dns.c
index 873eda377e17cdc42b5930c17eadd144600267f9..cd779bf2c33624189c6cdc3848804b2d13a5043a 100644 (file)
 /*********************************************************************
 *********************************************************************/
 
-int DoDNSUpdate( char *pszServerName, char *pszDomainName,
-                char *pszHostName, struct in_addr *iplist, int num_addrs )
+DNS_ERROR DoDNSUpdate(char *pszServerName,
+                     const char *pszDomainName, const char *pszHostName,
+                     const struct in_addr *iplist, size_t num_addrs )
 {
-       int32 dwError = 0;
-       DNS_ERROR dns_status;
-       HANDLE hDNSServer = ( HANDLE ) NULL;
-       int32 dwResponseCode = 0;
-       DNS_UPDATE_RESPONSE *pDNSUpdateResponse = NULL;
-#if 0
-       DNS_UPDATE_RESPONSE *pDNSSecureUpdateResponse = NULL;
-#endif
+       DNS_ERROR err;
+       struct dns_connection *conn;
+       TALLOC_CTX *mem_ctx;
+       OM_uint32 minor;
+       struct dns_update_request *req, *resp;
 
        if ( (num_addrs <= 0) || !iplist ) {
-               return -1;
+               return ERROR_DNS_INVALID_PARAMETER;
+       }
+
+       if (!(mem_ctx = talloc_init("DoDNSUpdate"))) {
+               return ERROR_DNS_NO_MEMORY;
+       }
+               
+       err = dns_open_connection( pszServerName, DNS_TCP, mem_ctx, &conn );
+       if (!ERR_DNS_IS_OK(err)) {
+               goto error;
+       }
+
+       /*
+        * Probe if everything's fine
+        */
+
+       err = dns_create_probe(mem_ctx, pszDomainName, pszHostName,
+                              num_addrs, iplist, &req);
+       if (!ERR_DNS_IS_OK(err)) goto error;
+
+       err = dns_update_transaction(mem_ctx, conn, req, &resp);
+       if (!ERR_DNS_IS_OK(err)) goto error;
+
+       if (dns_response_code(resp->flags) == DNS_NO_ERROR) {
+               TALLOC_FREE(mem_ctx);
+               return ERROR_DNS_SUCCESS;
+       }
+
+       /*
+        * First try without signing
+        */
+
+       err = dns_create_update_request(mem_ctx, pszDomainName, pszHostName,
+                                       iplist, num_addrs, &req);
+       if (!ERR_DNS_IS_OK(err)) goto error;
+
+       err = dns_update_transaction(mem_ctx, conn, req, &resp);
+       if (!ERR_DNS_IS_OK(err)) goto error;
+
+       if (dns_response_code(resp->flags) == DNS_NO_ERROR) {
+               TALLOC_FREE(mem_ctx);
+               return ERROR_DNS_SUCCESS;
        }
+
+       /*
+        * Okay, we have to try with signing
+        */
+       {
+               gss_ctx_id_t gss_context;
+               char *keyname;
+
+               if (!(keyname = dns_generate_keyname( mem_ctx ))) {
+                       err = ERROR_DNS_NO_MEMORY;
+                       goto error;
+               }
+
+               err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
+                                            keyname, &gss_context, DNS_SRV_ANY );
+
+               /* retry using the Windows 2000 DNS hack */
+               if (!ERR_DNS_IS_OK(err)) {
+                       err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
+                                                    keyname, &gss_context, 
+                                                    DNS_SRV_WIN2000 );
+               }
+               
+               if (!ERR_DNS_IS_OK(err))
+                       goto error;
                
-       dns_status = DNSOpen( pszServerName, DNS_TCP, &hDNSServer );
-       BAIL_ON_DNS_ERROR( dns_status );
 
-       dwError = DNSSendUpdate( hDNSServer, pszDomainName, pszHostName, 
-                                iplist, num_addrs, &pDNSUpdateResponse );
-       BAIL_ON_ERROR( dwError );
+               err = dns_sign_update(req, gss_context, keyname,
+                                     "gss.microsoft.com", time(NULL), 3600);
+
+               gss_delete_sec_context(&minor, &gss_context, GSS_C_NO_BUFFER);
+
+               if (!ERR_DNS_IS_OK(err)) goto error;
 
-       dwError = DNSUpdateGetResponseCode( pDNSUpdateResponse,
-                                           &dwResponseCode );
-       if ( dwResponseCode == DNS_REFUSED ) {
-               dwError = -1;
+               err = dns_update_transaction(mem_ctx, conn, req, &resp);
+               if (!ERR_DNS_IS_OK(err)) goto error;
+
+               err = (dns_response_code(resp->flags) == DNS_NO_ERROR) ?
+                       ERROR_DNS_SUCCESS : ERROR_DNS_UPDATE_FAILED;
        }
-       BAIL_ON_ERROR( dwError );
 
-cleanup:
-       return dwError;
 
 error:
-       goto cleanup;
+       TALLOC_FREE(mem_ctx);
+       return err;
 }
 
 /*********************************************************************
@@ -96,4 +160,23 @@ int get_my_ip_address( struct in_addr **ips )
        return count;
 }
 
+DNS_ERROR do_gethostbyname(const char *server, const char *host)
+{
+       struct dns_connection *conn;
+       struct dns_request *req, *resp;
+       DNS_ERROR err;
+
+       err = dns_open_connection(server, DNS_UDP, NULL, &conn);
+       if (!ERR_DNS_IS_OK(err)) goto error;
+
+       err = dns_create_query(conn, host, QTYPE_A, DNS_CLASS_IN, &req);
+       if (!ERR_DNS_IS_OK(err)) goto error;
+
+       err = dns_transaction(conn, conn, req, &resp);
+
+ error:
+       TALLOC_FREE(conn);
+       return err;
+}
+
 #endif /* defined(WITH_DNS_UPDATES) */